定時器與多線程 SetTimer and Multi-Thread 每一個線程獨立使用一個定時器 算法
生產者——消費者 模擬程序,需求以下: 多線程
因此個人解決方案以下: 函數
/* 更改定時器的消息 */ #define WM_SETTIMER WM_USER + 100 /* 生產者線程函數 */ DWORD WINAPI ProducerFunc(LPVOID lpParameter) { MSG msg; UINT producerTimerId; /* Create a message queue for this thread */ PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); producerTimerId = SetTimer(NULL, 0, g_uProducerTimer, NULL); while(GetMessage(&msg, NULL, 0, 0)) { if(msg.message == WM_TIMER) { WaitForSingleObject(g_hEmptySemaphore, INFINITE); WaitForSingleObject(g_hMutex, INFINITE); Producer(); ReleaseMutex(g_hMutex); ReleaseSemaphore(g_hFullSemaphore, 1, NULL); } else if(msg.message == WM_SETTIMER) { KillTimer(NULL, producerTimerId); producerTimerId = SetTimer(NULL, 0, g_uProducerTimer, NULL); } else { TranslateMessage(&msg); DispatchMessage(&msg); } } KillTimer(NULL, producerTimerId); return 0; } /* 消費者線程函數 */ DWORD WINAPI ConsumerFunc(LPVOID lpParameter) { MSG msg; UINT consumerTimerId; PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); consumerTimerId = SetTimer(NULL, 0, g_uConsumerTimer, NULL); while(GetMessage(&msg, NULL, 0, 0)) { if(msg.message == WM_TIMER) { WaitForSingleObject(g_hFullSemaphore, INFINITE); WaitForSingleObject(g_hMutex, INFINITE); Consumer(); ReleaseMutex(g_hMutex); ReleaseSemaphore(g_hEmptySemaphore, 1, NULL); } else if(msg.message == WM_SETTIMER) { KillTimer(NULL, consumerTimerId); consumerTimerId = SetTimer(NULL, 0, g_uConsumerTimer, NULL); } else { TranslateMessage(&msg); DispatchMessage(&msg); } } KillTimer(NULL, consumerTimerId); return 0; }
--------------------------------------------------------------------------- post
UINT_PTR hTimer = 0; //定時器消息處理函數 VOID __stdcall TimerProc(HWND hwnd,UINT uMsg,UINT_PTR idEvent,DWORD dwTime) { KillTimer(NULL,hTimer); MessageBox(NULL,"Speak in Timer!",":)",MB_OK); } //線程函數 DWORD __stdcall ThreadFun(void *) { MSG msg; PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE); hTimer = SetTimer(NULL,0,10,(TIMERPROC)TimerProc); while(!PeekMessage(&msg,NULL,WM_TIMER,WM_USER+1,PM_NOREMOVE)) { OutputDebugString("Not peek message\r\n"); Sleep(100); } if(msg.message == (WM_USER+1)) { //收到主線程發來的消息 OutputDebugString("Rec message\r\n"); } else { //收到定時器消息,派送之 OutputDebugString("what message\r\n"); DispatchMessage(&msg); } return 0; } //建立線程代碼: DWORD dwThreadId; HANDLE hThread = NULL; hThread = CreateThread(NULL,0,ThreadFun,NULL,0,&dwThreadId); if (hThread == NULL) { MessageBox("CreateThread failed.", "main", MB_OK ); } else { OutputDebugString("prepare post message\r\n"); Sleep(1000);//等待線程建立好了 PostThreadMessage(dwThreadId,WM_USER+1,0,0);//給線程發消息 OutputDebugString("Post message ok\r\n"); CloseHandle( hThread ); }
這是MFC的CWinThread類的實現。 首先建立一個線程 _beginthread(MainThread, DEFAULT_STACK_SIZE, NULL);
而後在MainThread中建立一個看不見的窗口(僞窗口):
this
WNDCLASS wcl; HWND hWnd = NULL; memset(&wcl,0,sizeof(wcl)); if (lpfnWndProc == NULL) { return NULL; /*失敗*/ } /*register class*/ wcl.cbClsExtra = 0; wcl.cbWndExtra = 0; wcl.hbrBackground = NULL; wcl.hCursor = NULL; wcl.hIcon = NULL; wcl.hInstance = NULL; wcl.lpfnWndProc = MainWindowProc; wcl.lpszClassName = szWndName; wcl.lpszMenuName = NULL; wcl.style = CS_VREDRAW; if (RegisterClass(&wcl) == 0) { return NULL; } /*create window*/ hWnd = CreateWindow(szWndName,NULL,WS_POPUP,0,0, CW_USEDEFAULT,CW_USEDEFAULT, NULL,NULL,NULL,NULL); /*進入消息循環*/ do { ret = GetMessage(&msg,NULL,0,0); if (ret > 0) { DispatchMessage(&msg); } }while(ret > 0); DestroySTUNServerWindow(szWndName, s_hSTUNServerWnd); 最後能夠在MainWindowProc中處理你的消息了: LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { default: return DefWindowProc(hWnd,uMsg,wParam,lParam); } return 0; }