多线程编程之线程安全退出

来源:互联网 发布:显示器尺寸 知乎 编辑:程序博客网 时间:2024/05/21 22:50

在多线程编程的时候,我们会建立线程去完成某项任务。例如杀毒软件点击开始后,就会创建一个线程开始杀毒。如果想取消杀毒,就会通过另外一个按钮来结束这个线程。但是该如何结束杀毒线程呢?
如果在windows下,该操作系统在ring3层提供了一个函数TerminateThread。原型如下
BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);
该函数能够“杀死”任何线程。hThread标识了要终止的那个线程的句柄。线程终止运行时,其退出代码将变成你作为dwExitCode参数传递的值。同时线程的内核对象的使用计数会递减。我在自己的一个模拟环境下试了一下,是可以停止的。我自己的环境是搜索指定目录下的文件,终止搜索的时候编辑框里的内容会停止变动。
HANDLE hcp;
void CMyDlg::OnBnClickedTest(){
hcp = CreateThread(NULL,0,CounerFunc,NULL,0,NULL);
//CounterFunc回调函数被调用,主要负责搜索目录功能。

}
void CMyDlg::OnBnClickedStop(){
DWORD *p = new DWORD[1];
GetExitCodeThread( hcp, p );
TerminateThread(hcp,*p);
delete []p;
} //使用该函数结束开始线程。
但是一个设计良好的应用程序决不会使用这个函数,因为被终止运行的线程收不到它被“杀死”的通知。线程无法正确清理,而且不能阻止自己被终止运行。(windows核心编程第五版)。此外,除非拥有此线程的进程终止运行,否则系统不会销毁这个线程的堆栈。
正确的方式就是让线程自己正常返回。如何正常返回呢?在结束线程里通过全局变量的形式或者一个事件的形式来告诉另外一个线程。
代码可如下表示:
HANDLE hcp;
HANDLE hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);//手动触发,开始未触发状态
DWORD WINAPI CounerFunc (LPVOID lpParameter)
{
while(TRUE){
……
for(unsigned int i = 0; i < g_dlg->ivectorSize(); i++) //主要负责搜索目录
{
if(WaitForSingleObject(hEvent,0) == WAIT_OBJECT_0){
CloseHandle(hEvent);
CloseHandle(hcp);
return 0;
} //使用WaitForSingleObject等待事件内核对象被触发,一旦被触发,返回//值便是WAIT_OBJECT_0。接着线程通过return 0直接返回
……
//如果没有通知该线程技术,继续做自己的工作
CheckFile(g_dlg->ivectorItem(i)); ///检查文件
}
……
}
return 0;
}
void CMyDlg::OnBnClickedTest(){
hcp = CreateThread(NULL,0,CounerFunc,NULL,0,NULL);
//CounterFunc回调函数被调用,主要负责搜索目录功能。

}
void CMyDlg::OnBnClickedStop(){
SetEvent(hEvent);//触发事件内核对象!
} //结束线程
另外一种方法就是设置一个BOOL类型的全局变量。开始时该值为FALSE,在结束线程里将改变量设为TRUE。
现在说一下线程函数返回时做了哪些工作。
1. 线程函数中创建的所有C++对象都通过其析构函数被正确销毁。
2. 操作系统正确释放线程栈使用的内存。
3. 操作系统把线程的退出代码设为线程函数的返回值。
4. 系统递减线程的内核对象的使用计数。

0 0
原创粉丝点击