windows核心编程之使用线程APC回调安全退出多个等待线程
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了windows核心编程之使用线程APC回调安全退出多个等待线程,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2919字,纯文字阅读大概需要5分钟。
内容图文
![windows核心编程之使用线程APC回调安全退出多个等待线程](/upload/InfoBanner/zyjiaocheng/1306/9baf258125624ba899af9300bbd23eaa.jpg)
前言
程序开发中经常遇到需要这些情况:辅助线程正在等待内核对象的触发,主线程需要强制终止辅助线程。我们常常做的就是使用:TerminateThread来强制终止线程。这样做当然是不太好的,强制终止线程后系统不会销毁此线程的堆栈,长久下去内存泄露问题就会很严重了。线程最安全的退出方式当然还是让它自己返回了。本文主要介绍windows核心编程中介绍的一种安全退出线程方式:使用可等待API等待内核对象触发,添加 线程APC回调。
API介绍
首先得简单介绍下一个重要的windows API
DWORD WINAPI QueueUserAPC( __in PAPCFUNC pfnAPC, __in HANDLE hThread, __in ULONG_PTR dwData );
函数允许我们手动将一个APC回调添加到指定线程队列中,回调函数:VOID WINAPI ApcCallback1(ULONG_PTR dwParam)
这个线程可以是系统中任何线程,如果标识的线程在另一个进程中,那么回调函数的地址也必须在另一个线程的地址空间中。
QueueUserAPC也可以用来强制让线程退出等待状态,当线程正在等待内核对象触发,可以使用它强制唤醒正在等待的线程,并让它将自己杀死。
另外就是Windows提供了6个API,可将线程的状态设置为可提醒状态。
SleepEx(
__in DWORD dwMilliseconds,
__in BOOL bAlertable
);
WaitForSingleObjectEx(
__in HANDLE hHandle,
__in DWORD dwMilliseconds,
__in BOOL bAlertable
);
WaitForMultipleObjectsEx(
__in DWORD nCount,
__in_ecount(nCount) CONST HANDLE *lpHandles,
__in BOOL bWaitAll,
__in DWORD dwMilliseconds,
__in BOOL bAlertable
);
SignalObjectAndWait(
__in HANDLE hObjectToSignal,
__in HANDLE hObjectToWaitOn,
__in DWORD dwMilliseconds,
__in BOOL bAlertable
);
GetQueuedCompletionStatusEx
MsgWaitForMultipleObjectsEx 使用MWMO_ALERTABLE标识线程进入可等待状态
这五个函数的老版本API,即不带Ex的在内部实现都是调用对应的Ex函数,传入bAlertable=FALSE。
在可提醒I/O中将对这些函数的调用以及完成回调、APC回调进行详细的介绍,这里暂时省略了。
实例代码
//给每一个线程标记上一个索引值 volatile LONG g_nIndex = 0; UINT __stdcall Thread1(void* lpParam) { //使用原子锁来操作实现用户模式下的线程同步,更加快捷 LONG lPrevIndex = InterlockedExchangeAdd(&g_nIndex, 1);//我们需要记录原始值 LONG lCurIndex = lPrevIndex + 1; cout<<"线程"<<lCurIndex<<"开始执行"<<endl; while( true ) { //cout<<"Thread1:"<<nIndex<<endl; //休眠一秒钟,线程进入可提醒状态 if ( WAIT_IO_COMPLETION == SleepEx(1000, TRUE) ) {//此时,我们添加一项到APC队列中了,线程可以退出了 break; } //nIndex++; } cout<<"线程"<<lCurIndex<<"正常退出"<<endl; return 0; } //APC回调函数 VOID WINAPI ApcCallback(ULONG_PTR dwParam) { //由于只是为了让线程立即正常退出,而不必杀死线程,我们在这里可以不做任何处理 cout<<"ApcCallback:线程的APC回调函数执行"<<endl; } bool ApcTest() { const int nThreadCount = 10; HANDLE hThread[nThreadCount]; int i = 0; for ( int i=0; i<nThreadCount; ++i ) hThread[i] = (HANDLE)_beginthreadex(NULL, 0, Thread1, NULL, 0, NULL); DWORD dwError, dwRet; while( true ) { dwRet = WaitForMultipleObjects(nThreadCount, hThread, TRUE, 10*1000); if ( dwRet == WAIT_TIMEOUT ) {//等待超时,想办法强制终止线程 //由于辅助线程休眠时进入可等待状态,手动添加回调到APC队列将导致毁掉执行完后线程清空队列,线程退出可提醒状态 //此时,友好地退出线程。 for ( i=0; i<nThreadCount; ++i ) { dwRet = QueueUserAPC(ApcCallback, hThread[i], 2015); if ( dwRet == 0 ) {//添加APC回调到线程APC队列失败 dwError = GetLastError(); break; } } continue; } if ( WAIT_OBJECT_0 == dwRet ) { cout<<"辅助线程均已退出,循环退出…………"<<endl; break; } } for ( i=0; i<nThreadCount; ++i ) CloseHandle(hThread[i]); return true; }
程序运行
总结
主要就是在线程等待时,使用那些扩展的API(带Ex),使线程进入可等待状态。这时,系统会先检查线程的APC队列。由于我们向线程的APC队列中人为添加了一个回调函数,队列不为空则调用APC函数,清空队列。然后函数执行完毕返回WAIT_IO_COMPLETION,这时我们就知道是自己添加了一个APC回调,引导线程自己退出。从而实现多个等待线程安全地退出等待状态。
原文:http://blog.csdn.net/mfcing/article/details/44303063
内容总结
以上是互联网集市为您收集整理的windows核心编程之使用线程APC回调安全退出多个等待线程全部内容,希望文章能够帮你解决windows核心编程之使用线程APC回调安全退出多个等待线程所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。