terminatethread
定义
terminatethread是Win32 API中用于结束一个已存在线程的函数,其原型为 $BOOL\ TerminateThread(HANDLE\ hThread,\ DWORD\ dwExitCode)$,两个参数分别是被终止线程的句柄与写入该线程的退出码[1]。函数执行成功返回非零值,失败返回零,具体错误原因需通过 GetLastError 查询[1]。线程结束后的退出代码可以用 GetExitCodeThread 读取[1]。
它与同样用于结束线程的 ExitThread 有本质区别:ExitThread 由线程自身调用,而 TerminateThread 由外部线程持有句柄发起,属于异步的强制手段[2]。微软文档给出线程结束的几种途径,包括线程函数返回、调用 ExitThread、进程内任一 线程 对目标句柄调用 TerminateThread、以及调用 TerminateProcess 结束整个 进程[2]。
原理
调用发生后,系统并不等待目标线程执行到安全点,而是直接令其退出,因此目标线程没有任何机会再运行用户模式代码,系统随即释放该线程的初始栈[1]。线程对象的终止状态由 STILL_ACTIVE 变为调用者传入的 dwExitCode 值,对象状态转为已触发,从而唤醒所有等待该线程结束的其他线程[1]。
结束线程并不等于删除线程对象,内核对象的引用计数要等到最后一个线程句柄被 CloseHandle 关闭后才归零并销毁[2]。若被终止的线程恰是该进程的最后一个活动线程,整个进程也会随之结束[1]。该函数是异步的,调用返回时并不保证线程已被撤销,通常还需要配合 WaitForSingleObject 等函数确认其真正退出[1]。
flowchart LR
A[调用方线程] -->|持有 THREAD_TERMINATE 句柄| B[TerminateThread]
B --> C[目标线程停止运行]
C --> D[退出码写入线程对象]
D --> E[线程对象置为已触发]
E --> F[等待该线程者被唤醒]
E --> G[关闭最后句柄后对象销毁]
发展历程
该函数自Windows NT系列桌面系统起提供,微软文档标注的最低客户端为 Windows XP、最低服务器为 Windows Server 2003,头文件为 processthreadsapi.h,并需链接 Kernel32.lib、依赖 Kernel32.dll[1]。在嵌入式平台方面,Windows CE 1.01 及以后版本亦提供该函数,头文件为 Winbase.h,链接库为 Coredll.lib[3]。
早期版本的实现存在差异:在 Windows Server 2003 与 Windows XP 上,被终止线程的初始栈不会被释放,会造成资源泄漏,后续版本的文档则说明系统会释放该栈[1]。在 Windows CE 的文档中,还记录了另一种限制——线程若正在执行系统 API 调用则无法被终止,须等该调用返回用户地址空间后才生效[3]。
应用
该函数主要用于处理失去响应或无法通过正常途径结束的线程,例如线程陷入死锁、等待永不满足的条件,或运行的是无法修改的第三方代码[1]。典型写法是先用 OpenThread 以 THREAD_TERMINATE 权限取得目标线程句柄,再调用 TerminateThread 并传入退出码,最后用 CloseHandle 关闭句柄[4]。
在采用该函数的场合,工程实践通常把它作为兜底手段置于协作式退出之后:先发出退出信号并等待一段时间,超时仍未结束的线程才被强制终止[4]。终止完成后仍需关闭句柄,否则线程内核对象不会立即释放[2]。
局限
微软明确将该函数称为危险的函数,认为它只应在最极端的情况下调用,前提是调用者对目标线程当时正在执行的代码有完整掌握[1]。如果目标线程持有 临界区,该临界区不会被释放;如果线程正在从堆上分配内存,堆锁也不会被解除[1]。
其他风险包括:线程在终止瞬间正在执行某些 kernel32 调用时,进程的 kernel32 状态可能变得不一致;线程若在改动共享 DLL 的全局状态,DLL 状态可能被破坏并波及该 DLL 的其他使用者[1]。附加到线程的 DLL 也收不到线程正在终止的通知,无法执行 DLL_THREAD_DETACH 一类的清理流程[2]。
线程自身几乎无法防御这种终止,只能通过控制句柄访问权限来实现,而 CreateThread 与 CreateProcess 返回的句柄默认带有 THREAD_TERMINATE 权限,任何持有该句柄的调用者都可以结束该线程[1]。SEI CERT 的 Windows 安全编码规范因此把强制终止执行列为应避免的做法,建议改用协作式退出[4]。更稳妥的方案是创建 事件对象,各线程以 WaitForSingleObject 监视其状态,收到信号后自行返回入口点或调用 ExitThread 结束[2]。
参见
-
ExitThread —— 由线程自身调用以结束当前线程的函数,是该函数之外更常见的退出途径。
-
TerminateProcess —— 用于结束整个进程,同样不通知 DLL 且不给予清理机会。
-
CreateThread —— 创建线程的函数,其返回句柄默认具有 THREAD_TERMINATE 权限。
-
GetExitCodeThread —— 读取线程退出代码的函数,常与该函数配合使用。
-
临界区 —— 线程同步对象,目标线程被强制终止时可能无法释放。
参考资料
- TerminateThread 函数 (processthreadsapi.h) [引用日期2026-10-19]
- terminating-a-thread [引用日期2026-10-19]
- ms918434(v=msdn [引用日期2026-10-19]
- viewpage [引用日期2026-10-19]