之前在用到等待函数的时候,总是认为等待一个事件、信号量等等,但是忽视了进程线程对象也是一个可以等待的内核对象。
进程或者线程内核对象(其中有一个BOOL类型)在创建的时候总是处于未触发状态,当进程线程终止的时候,操作系统会将其设置为触发状态,而且决回不到未触发的状态,但是如果等待的是事件,事件可是可以回到未触发的状态。
DWORD WaitForSingleObject(HANDLE hOBject,DWORD dwMilliseconds);
hOBject: 内核对象句柄
dwMilliseconds:等待多长时间
eg:
DWORD dw=WaitForSingleObject(hProcess,5000);
switch(dw){
case WAIT_OBJECT_0: //等待对象触发的原因: 进程结束了 或者线程
break;
case WAIT_TIMEOUT: //等待超过预定的时间 等待的时间过了,就算内核对象没有触发函数也会返回
break;
case WAIT_FAILED: //等待函数调用失败 有的时候 GetLastError()
break;
}
DWORD WaitForMultipleObjects(DWORD dwCount,CONST HANDLE *phObject,BOOL bWaitAll,DWORD dwMilliiseconds);
dwCount必须在1到MAXIMUM_WAIT_OBJECTS(64)之间,即等待多少个。
phObject:被等待对象句柄数组的首地址。
bWaitAll:是一有一个对象触发函数就返回和等待所有的内核对象都触发后函数才返回。
eg: HANDLE h[2];
h[0]=hProcess1;h[1]=hProcess2;
while(
DWORD dw=WaitForMultipleObjects(2,h,FALSE,5000);
switch(dw){
case WAIT_TIMEOUT: //等待超时
break;
case WAIT_OBJECT_0+0: //1号进程结束 1号内核对象触发
break;
case WAIT_OBJECT_0+1: //2号进程结束 2号内核对象触发
break;
)
重点:
但是,如果是事件的话,等待成功后系统会把已经触发的事件重新设置为未触发的状态,所以不停的循环并没有什么事情,但是像进程线程的结束,如果一个进程结束,传入的两个进程数组还是原来的那个样子,那样返回值还是会立即返回WAIT_OBJECT_0,除非在第一次捕捉到进程内核对象触发的时候就对while循环外的句柄数组手动去掉已经触发的那个句柄。
然后用 事件 的内核对象就是尽量使用WaitForMultipleObjects()这个函数是使用原子方式执行操作。假设线程正在等待一个自动的重置事件按对象,当事件对象被触发的时候,函数会检测到这个情况,这时候它直接返回WAIT_OBJECT_0给调用的线程,并且它会自动使事件重新变为非触发的状态,不需要手动修改数组,如果还有其他的线程在等待这个事件的触发,那么这就是副作用的地方。
而且线程的优先级对于各个线程等待函数收到通知的机会没有影响。
DWORD SingleObjectAndWait(HANDLE hObjectToSingal, HADNLE hObjectToWait,DWORD dwMillioseconds,BOOL bAlertable );
标志bAlertable:表示当前线程处于等待状态的时候,是否应该能够对添加到队列中的异步过程调用进行处理(可提醒状态)
函数的作用是使一个内核对象变为触发状态并且等待另一个内核对象。
hObjectToSingal:要成为触发状态的内核对象句柄。
hObjectToWait:要等待的内核对象句柄。