首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 操作系统 > windows >

Windows停三种激活阻塞线程的方法

2013-10-23 
Windows下三种激活阻塞线程的方法多线程编程经常遇到以下问题:主线程退出前,后台线程也优雅的退出。如果后

Windows下三种激活阻塞线程的方法

多线程编程经常遇到以下问题:主线程退出前,后台线程也优雅的退出。如果后台线程处于阻塞状态,则需要把阻塞线程激活。本文讨论Windows下面,三种激活阻塞线程的方法。


第一种:利用WaitForMultipleObjects函数让线程处于阻塞状态,并设置多个等待对象中的任一对象处于signal状态下都返回。此时向WaitForMultipleObjects传递的等待对象数组要包含一个额外的通知对象,主线程通过signal该通知对象,来激活阻塞线程。


第二种:利用MsgWaitForMultipleObjects函数让线程处于阻塞状态,并设置任何消息都可以使该函数返回。在返回后检查消息的类型,如果不是特定的通知消息,则继续调用MsgWaitForMultipleObjects;否则阻塞线程返回。此时主线程通过PostThreadMessage函数向阻塞线程发送指定的通知消息,来激活阻塞线程。这种方法要求阻塞线程具有消息循环,没有消息循环的线程可以通过调用PeekMessage等函数强制建立消息循环。

 

第三种:利用SleepEx,SignalObjectAndWait,WaitForSingleObjectEx,WaitForMultipleObjectsEx,或MsgWaitForMultipleObjectsEx函数使得线程处于alertable阻塞状态。此时主线程通过QueueUserAPC函数向阻塞线程发送一个APC对象,使得阻塞线程从阻塞中返回。


以下代码用MsgWaitForMultipleObjectsEx函数演示了这三种方法。

#include "stdafx.h"#include <Windows.h>#include <process.h>#include <stdio.h>HANDLE hStartEvent; // thread start event HANDLE hStopEvent;// thread stop event unsigned _stdcall ThreadProc(PVOID param){// 创建消息循环,并通知主线程消息循环创建成功MSG tmpMsg;PeekMessage(&tmpMsg, NULL, WM_USER, WM_USER, PM_NOREMOVE);if (!SetEvent(hStartEvent)) //set thread start event return 1;HANDLEarEvents[1] = { hStopEvent } ;while (TRUE){MSG msg ; while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) { if (msg.message == WM_QUIT)  { // quit msgprintf("quit msg received\n");return 0 ; }DispatchMessage(&msg); } DWORD result ; result = MsgWaitForMultipleObjectsEx( 1 , arEvents , INFINITE, QS_ALLINPUT, MWMO_ALERTABLE ); if (result == WAIT_OBJECT_0 + 1) // msg received{continue;} else if(result == WAIT_OBJECT_0){ // stop eventprintf("stop event signaled\n");return 0;}else if(result == WAIT_IO_COMPLETION ){ // apcprintf("iocp received\n");return 0;}}}void _stdcall APCProc(ULONG_PTR dwParam){// nothing to do}int _tmain(int argc, _TCHAR* argv[]){HANDLE hThread;unsigned nThreadID;hStartEvent = ::CreateEvent(0,FALSE,FALSE,0);hStopEvent = ::CreateEvent(0, FALSE, FALSE, 0);if(hStartEvent == 0){printf("create start event failed,errno:%d\n",GetLastError());return 1;}//start threadhThread = (HANDLE)_beginthreadex( NULL, 0, &ThreadProc, NULL, 0, &nThreadID );if(hThread == 0){printf("start thread failed,errno:%d\n",GetLastError());CloseHandle(hStartEvent);return 1;}// 等待线程启动消息循环::WaitForSingleObject(hStartEvent,INFINITE);CloseHandle(hStartEvent);#ifdef METHOD_EVENT// 第一种方法,激活线程正在等待的事件::SetEvent(hStopEvent);#else#ifdef METHOD_MSG// 第二种方法,向线程发送消息if( !PostThreadMessage(nThreadID, WM_QUIT, 0, 0)){printf("post message failed,errno:%d\n",GetLastError());}#else#ifdef METHOD_APC// 第三种方法,向线程推送一个UserAPCif(QueueUserAPC(APCProc, hThread, 0) == 0){printf("QueueUserAPC failed,errno:%d\n",GetLastError());}#else#pragma message("Error: define METHOD_EVENT or METHOD_MSG or METHOD_APC")#endif#endif#endif// 等待线程退出if(WaitForSingleObject(hThread, INFINITE) != WAIT_OBJECT_0){printf("WaitForSingleObject failed,errno:%d\n",GetLastError());}CloseHandle(hThread);return 1;}


热点排行