class CritSect { public: friend class Lock; CritSect() { InitializeCriticalSection(&_critSection); } ~CritSect() { DeleteCriticalSection(&_critSection); } private: void Acquire(){ EnterCriticalSection(&_critSection); } void Release(){ LeaveCriticalSection(&_critSection); } CRITICAL_SECTION _critSection; }; class Lock { public: Lock(CritSect& critSect):_critSect(critSect) { _critSect.Acquire(); } ~Lock(){ _critSect.Release(); } private: CritSect& _critSect; };调用:CritSect sect; Lock lock(sect);
DWORD dw = WaitForSingleObject(hProcess, 5000); switch(dw) { case WAIT_OBJECT_0: // The process terminated. break; case WAIT_TIMEOUT: // The process did not terminate within 5000 milliseconds. break; case WAIT_FAILED: // Bad call to function (invalid handle?) break; }
HANDLE h[3]; h[0] = hProcess1; h[1] = hProcess2; h[2] = hProcess3; DWORD dw = WaitForMultipleObjects(3, h, FALSE, 5000); switch(dw) { case WAIT_FAILED: // Bad call to function (invalid handle?) break; case WAIT_TIMEOUT: // None of the objects became signaled within 5000 milliseconds. break; case WAIT_OBJECT_0 + 0: // The process identified by h[0] (hProcess1) terminated. break; case WAIT_OBJECT_0 + 1: // The process identified by h[1] (hProcess2) terminated. break; case WAIT_OBJECT_0 + 2: // The process identified by h[2] (hProcess3) terminated. break; }
3)SingleObjectAndWait()
DWORD SingleObjectAndWait(HANDLE hObjectToSignal,HANDLE hObjectToWaitOn,DWORD dwMilliseconds,BOOL fAlertable);
函数用于在单个原子方式的操作中发出关于内核对象的通知并等待另一个内核对象:hObjectToSignal参数必须标识一个互斥对象、信号对象或事件对象。hObjectToWaitOn参数用于标识下列任何一个内核对象:互斥对象、信标、事件、定时器、进程、线程、作业、控制台输入和修改通知。与平常一样,dwMilliseconds参数指明该函数为了等待该对象变为已通知状态,应该等待多长时间,而fAlertable标志则指明线程等待时该线程是否应该能够处理任何已经排队的异步过程调用。
4)MsgWaitForMultipleObjects(Ex)
MsgWaitForMultipleObjects和MsgWaitForMultipleObjectsEx这些函数与WaitForMultipleObjects函数十分相似。差别在于它们允许线程在内核对象变成已通知状态或窗口消息需要调度到调用线程创建的窗口中时被调度。创建窗口和执行与用户界面相关的任务的线程,应该调用MsgWaitForMultipleObjectsEx函数,而不应该调用WaitForMultipleObjects函数,因为后面这个函数将使线程的用户界面无法对用户作出响应。
Windows下的生产者消费者问题:推荐使用Semaphore版本,因为使用mutex版本时候,两个线程不能并行工作。
#include "StdAfx.h" #include <windows.h> #include <stdio.h> #define BUFFER_SIZE 10 typedef struct Prodcon { int readpos; int writepos; //position for reading and writing int buffer[BUFFER_SIZE]; }Prodcon; bool isOver = false; HANDLE hmutex; HANDLE hfullsemaphore; HANDLE hemptysemaphore; HANDLE notfullevent; HANDLE notemptyevent; void init(Prodcon * pb) { pb->readpos = 0; pb->writepos = 0; } //store an integer in the buffer void put(Prodcon* pb,int data) { WaitForSingleObject(hemptysemaphore,INFINITE); pb->buffer[pb->writepos] = data; pb->writepos++; pb->writepos %= BUFFER_SIZE; ReleaseSemaphore(hfullsemaphore,1,NULL); } //read an integer from the buffer int get(Prodcon* pb) { int data; WaitForSingleObject(hfullsemaphore,INFINITE); data = pb->buffer[pb->readpos]; pb->readpos ++; pb->readpos %= BUFFER_SIZE; ReleaseSemaphore(hemptysemaphore,1,NULL); return data; } //put data use event trigger void put_event(Prodcon* pb,int data) { WaitForSingleObject(hmutex,INFINITE); //wait until buffer is not full while((pb->writepos+1)%BUFFER_SIZE == pb->readpos) { printf("wait for not full\n"); ReleaseMutex(hmutex); WaitForSingleObject(notfullevent,INFINITE); } pb->buffer[pb->writepos] = data; pb->writepos ++; pb->writepos %= BUFFER_SIZE; SetEvent(notemptyevent); ReleaseMutex(hmutex); } //get data use event trigger int get_event(Prodcon* pb) { int data; WaitForSingleObject(hmutex,INFINITE); //wait until buffer is not empty while(pb->writepos == pb->readpos) { printf("wait for not empty\n"); ReleaseMutex(hmutex); WaitForSingleObject(notemptyevent,INFINITE); } data = pb->buffer[pb->readpos]; pb->readpos ++; pb->readpos %= BUFFER_SIZE; SetEvent(notfullevent); ReleaseMutex(hmutex); return data; } DWORD WINAPI produce(LPVOID lppara) { Prodcon* pb = (Prodcon*)lppara; while(1) { for(int i=1; i<=50; ++i) { //put(pb,i); //test event trigger function put_event(pb,i); printf("put a data: %d\n",i); Sleep(10); //producer is fast } isOver = true; break; } return NULL; } DWORD WINAPI consume(LPVOID lppara) { Prodcon* pb = (Prodcon*)lppara; while(1) { //int d = get(pb); //test event trigger function int d = get_event(pb); printf("get data: %d\n",d); if(isOver == true && pb->readpos == pb->writepos) { printf("OVER!\n"); break; } Sleep(100); //consumer is slow } return NULL; } int main() { hmutex = CreateMutex(NULL,false,NULL); DWORD readerdata; DWORD writerdata; Prodcon pb; init(&pb); //test produce/consume semaphore trigger /*hfullsemaphore = CreateSemaphore(NULL,0,BUFFER_SIZE,NULL); hemptysemaphore = CreateSemaphore(NULL,BUFFER_SIZE,BUFFER_SIZE,NULL); if(CreateThread(NULL,0,produce,&pb,0,&writerdata)==NULL) return -1; if(CreateThread(NULL,0,consume,&pb,0,&readerdata)==NULL) return -1;*/ //test produce/consume Event trigger notfullevent = CreateEvent(NULL,FALSE,FALSE,NULL); //unnamed auto-reset event notemptyevent = CreateEvent(NULL,FALSE,FALSE,NULL); //unnamed auto-reset event if(CreateThread(NULL,0,produce,&pb,0,&writerdata)==NULL) return -1; if(CreateThread(NULL,0,consume,&pb,0,&readerdata)==NULL) return -1; char ch; while(1) { ch = getchar(); //press "e" to exit if(ch == 'e') break; } printf("Program ends successfully\n"); CloseHandle(hmutex); CloseHandle(hfullsemaphore); CloseHandle(hemptysemaphore); return 0; }
参考资料:
http://msdn2.microsoft.com/en-us/library/ms686360(VS.85).aspx