http://www.pczpg.com/a/2010/0425/6555.html
终止线程运行
若要终止线程的运行,可以使用下面的方法:
• 线程函数返回(最好使用这种方法)。
• 通过调用 ExitThread 函数,线程将自行撤消(最好不要使用这种方法)。
• 同一个进程或另一个进程中的线程调用 TerminateThread 函数(应该避免使用这种方法)。
• 包含线程的进程终止运行(应该避免使用这种方法)。
下面将介绍终止线程运行的方法,并且说明线程终止运行时会出现什么情况。
线程函数返回
始终都应该将线程设计成这样的形式,即当想要线程终止运行时,它们就能够返回。这是确保所有线程资源被正确地清除的唯一办法。
如果线程能够返回,就可以确保下列事项的实现:
• 在线程函数中创建的所有 C++ 对象均将通过它们的撤消函数正确地撤消。
• 操作系统将正确地释放线程堆栈使用的内存。
• 系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值。
• 系统将递减线程内核对象的使用计数。
使用 ExitThread 函数
可以让线程调用 ExitThread 函数,以便强制线程终止运行:
VOID ExitThread(DWORD dwExitCode);
该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C++ 资源(如 C++ 类对象)将不被撤消。由于这个原因,最好从线程函数返回,而不是通过调用 ExitThread 来返回。
当然,可以使用 ExitThread 的 dwExitThread 参数告诉系统将线程的退出代码设置为什么。ExitThread 函数并不返回任何值,因为线程已经终止运行,不能执行更多的代码。
使用 TerminateThread 函数
调用 TerminateThread 函数也能够终止线程的运行:
BOOL TerminateThread(HANDLE hThread, DWORD dwExitCode);
与 ExitThread 不同,ExitThread 总是撤消调用的线程,而 TerminateThread 能够撤消任何线程。hThread 参数用于标识被终止运行的线程的句柄。当线程终止运行时,它的退出代码成为你作为 dwExitCode 参数传递的值。同时,线程的内核对象的使用计数也被递减。
注意 TerminateThread 函数是异步运行的函数,也就是说,它告诉系统你想要线程终止运行,但是,当函数返回时,不能保证线程被撤消。如果需要确切地知道该线程已经终止运行,必须调用 WaitForSingleObject 或者类似的函数,传递线程的句柄。
设计良好的应用程序从来不使用这个函数,因为被终止运行的线程收不到它被撤消的通知。线程不能正确地清除,并且不能防止自己被撤消。
注意 当使用返回或调用 ExitThread 的方法撤消线程时,该线程的内存堆栈也被撤消。但是,如果使用 TerminateThread,那么在拥有线程的进程终止运行之前,系统不撤消该线程的堆栈。Microsoft故意用这种方法来实现 TerminateThread。如果其他仍然正在执行的线程要引用强制撤消的线程堆栈上的值,那么其他的线程就会出现访问违规的问题。如果将已经撤消的线程的堆栈留在内存中,那么其他线程就可以继续很好地运行。
此外,当线程终止运行时,DLL 通常接收通知。如果使用 TerminateThread 强迫线程终止,DLL 就不接收通知,这能阻止适当的清除。
在进程终止运行时撤消线程
我们知道,进程函数 ExitProcess 和 TerminateProcess 也可以用来终止线程的运行。差别在于这些线程将会使终止运行的进程中的所有线程全部终止运行。另外,由于整个进程已经被关闭,进程使用的所有资源肯定已被清除。这当然包括所有线程的堆栈。这两个函数会导致进程中的剩余线程被强制撤消,就像从每个剩余的线程调用 TerminateThread 一样。显然,这意味着正确的应用程序清除没有发生,即 C++ 对象撤消函数没有被调用,数据没有转至磁盘等等。
线程终止运行时发生的操作
当线程终止运行时,会发生下列操作:
• 线程拥有的所有用户对象均被释放。在 Windows 中,大多数对象是由包含创建这些对象的线程的进程拥有的。但是一个线程拥有两个用户对象,即窗口和挂钩。当线程终止运行时,系统会自动撤消任何窗口,并且卸载线程创建的或安装的任何挂钩。其他对象只有在拥有线程的进程终止运行时才被撤消。
• 线程的退出代码从 STILL_ACTIVE 改为传递给 ExitThread 或 TerminateThread 的代码。
• 线程内核对象的状态变为已通知。
• 如果线程是进程中最后一个活动线程,系统也将进程视为已经终止运行。
• 线程内核对象的使用计数递减 1。
当一个线程终止运行时,在与它相关联的线程内核对象的所有未结束的引用关闭之前,该内核对象不会自动被释放。
一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用 GetExitcodeThread 来检查由 hThread 标识的线程是否已经终止运行。如果它已经终止运行,则确定它的退出代码:
BOOL GetExitCodeThread(HANDLE hThread, PDOWRD pdwExitCode);
退出代码的值在 pdwExitCode 指向的 DWORD 中返回。如果调用 GetExitCodeThread 时线程尚未终止运行,该函数就用 STILL_ACTIVE 标识符(定义为 0x103)填入 DWORD。如果该函数运行成功,便返回 TRUE。
分享到:
相关推荐
在MFC中,CWinThread类提供了StartThread()函数来启动线程,而AfxEndThread()用于终止线程。线程的暂停和恢复可以通过挂起(SuspendThread)和恢复(ResumeThread)API来实现,但需要注意的是,挂起线程可能会导致...
例如,`CreateThread`函数用于创建新线程,`SetThreadPriority`用于设置线程的优先级,而`TerminateThread`和`ExitThread`则分别用于外部和内部终止线程。 #### MFC与多线程 对于追求更高层次抽象和便捷性的开发者...
线程有创建、运行、等待、挂起、恢复和终止等生命周期状态。`WaitForSingleObject`或`WaitForMultipleObjects`函数可以用来等待线程完成。线程的终止通过`ExitThread`或关闭线程句柄(`CloseHandle`)实现。 六、...
3. 线程管理:创建后的线程可以独立于主线程运行,开发者需要考虑线程的生命周期,包括等待、恢复、终止线程等操作。 4. 线程同步:为了防止数据竞争和死锁,需要使用互斥量(Mutex)、信号量(Semaphore)、事件...
控制线程的生命周期非常重要,尤其是在需要终止线程的情况下。 1. **终止并等待线程完成**: ```delphi if MsgThread <> nil then begin MsgThread.Terminate; MsgThread.WaitFor; end; ``` 上述代码首先...
在IT领域,多线程编程是一项基础且重要的技术,尤其在Windows操作系统环境下。"实验一:WindowsThreads多线程编程实验"旨在让...通过仔细阅读、分析和调试这些文件,学生将能够全面掌握Windows平台上的多线程编程技巧。
需要注意的是,终止线程可能需要处理一些资源释放等问题: ```delphi procedure TForm1.Button2Click(Sender: TObject); begin if MyThread <> nil then MyThread.Terminate; end; ``` 此外,还可以通过`...
线程创建后,会一直运行直到其Run()函数返回或者被显式地终止。线程退出前,应确保所有资源已被释放,且没有其他线程正在等待该线程完成。使用AfxEndThread()函数可优雅地结束线程。 6. **性能优化** 虽然多线程...
需要注意的是,非正常终止线程可能导致资源泄露,因此应当谨慎使用`TerminateThread`。 5. **线程安全**: 多线程编程中的一个核心问题是如何保证数据一致性。线程安全的实现通常包括互斥访问、原子操作、条件变量...
这本书不仅深入讨论了Windows 95与Windows NT在实现上的差异,而且提供了大量的编程技巧和实践范例,帮助读者在理解理论的同时能够将知识应用于实际开发中。 书中特别强调了32位Windows编程的重要性,因为随着...
此外,文档可能还会涵盖线程的优先级、线程池、线程的挂起与恢复,以及进程的终止和资源释放等主题。 另一方面,"www.pudn.com.txt"这个文件可能是来源于网络论坛pudn.com的资源链接或者相关讨论,可能包含了更多...
5. **线程的生命周期管理**:线程创建后,需要妥善管理其生命周期,包括等待线程结束(`WaitForSingleObject`)、终止线程(`TerminateThread`,应谨慎使用)以及清理线程资源(`CloseHandle`)。 6. **线程安全的...
在编程领域,多线程是一种重要的并发执行方式,尤其在现代计算机系统中,它能显著提升...通过分析和调试`WinThreadDemoApplication`,你可以深入掌握线程的生命周期、同步机制以及在Windows环境下的多线程编程技巧。
在Windows编程中,多线程允许程序同时执行多个独立的任务,每个任务都在自己的线程上下文中运行。这样的设计可以改善用户界面的响应性,比如在后台执行耗时操作的同时,用户界面仍然保持活跃。此外,多线程也常用于...
6.3.2 挂起、恢复、切换、终止线程 164 6.3.3 创建远程线程、将代码注入其他进程中执行 167 6.3.4 创建纤程、删除纤程、调度纤程 170 6.3.5 纤程与线程的互相转换 171 6.4 进程状态信息 176 6.4.1 PS API...
- 线程创建与销毁:展示如何创建新的线程并让它执行特定任务,然后安全地终止线程。 - 线程同步:通过Mutex、Semaphore或Event实现线程间的同步,防止数据竞争和死锁。 - 临界区和原子操作:演示如何使用临界区保护...
- **ExitThread和TerminateThread函数**:分别用于正常结束线程和强制终止线程,使用时需谨慎,尤其是后者可能导致数据不一致。 - **Thread Local Storage (TLS)**:每个线程都有自己的存储空间,用于存放线程特有...