目录
“TerminateThread() 是一个危险的函数,应该在最不得已的情况下才使用”
不要让线程成为脱缰野马
这一章描述如何初始化一个新线程,如何停止一个执行中的线程,以及如 何了解并调整线程优先权。
1,干净地终止一个线程
1)利用 TerminateThread() 放弃一个线程
BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode ); ---------------------------------------------------------------- 参数 ---------------------------------------------------------------- hThread 欲令其结束之线程的 handle 。该线程就是我们的 行动目标。 ---------------------------------------------------------------- dwExitCode 该线程的结束代码。 ---------------------------------------------------------------- 返回值 如果函数成功,则传回 TRUE。如果失败,则传回 FALSE。GetLastError() 可以获知更多细节。 ----------------------------------------------------------------
“TerminateThread() 是一个危险的函数,应该在最不得已的情况下才使用”
这个函数不会在目 标线程中丢出一个异常情况(exception),目标线程在核心层面就被根本抹杀 了。目标线程没有机会捕捉所谓的“结束请求”,并从而获得清理自己的机会。
目标线程的堆栈没有被释放掉,于是可能 会引起一大块内存泄漏(memory leak)。而且,任何一个与此线程有附着关系 的 DLLs 也都没有机会获得“线程解除附着”的通知。
2) 跨越线程,丢出异常情况(Exceptions)
Win32 API 中没有 什么标准方法可以把一个异常情况丢到另一个线程中
3)设立一个标记
worker线程中有一个循环检查一个event。
2,线程优先权(Thread Priority)
1)优先权的计算基准:进程的“优先权类别(priority class)”、线程的“优先权层级 (priority level)”和操作系统当时采用的“动 态提升(Dynamic Boost )”所有因素放在一起,最后获得一 个 0~31 的数值。拥有最高优先权之线程,即为下一个将执行起来的线程
2)优先权类别(Priority Class)
“优先权类别”是进程的属性之一。
大部分程序使用 NORMAL_PRIORITY_CLASS。
3)优先权层级(Priority Level)
1>改变优先权层级
BOOL SetThreadPriority( HANDLE hThread, int nPriority ); ------------------------------------------------------------- 参数 ------------------------------------------------------------- hThread 代表欲调整优先权的那个线程。 ------------------------------------------------------------- nPriority 表格 5-2 所显示的数值。 ------------------------------------------------------------- 返回值 如果函数成功,就传回表格 5-2 所列的其中一个值。如果函数失败,就传 回 FALSE 。GetLastError() 可以获得更详细的信息。 线程目前的优先权层级可以利用 GetThreadPriority () 获知。 ------------------------------------------------------------- int GetThreadPriority( HANDLE hThread ); ------------------------------------------------------------- 参数 ------------------------------------------------------------- hThread 代表一个线程 ------------------------------------------------------------- 返回值 如果函数成功,就传回 TRUE 。如果函数失败,就传回 THREAD_PRIORITY_ERROR_RETURN。GetLastError() 可以获得更详细的信息。 -------------------------------------------------------------
3)动态提升(Dynamic Boost)
所谓动态提升是对优先权的一种调整,使系统能够机动对待线程, 以强化程序的可用性。
1> 便是 Window s N T 施行于所有前台程序的“线程 动态提升”
2> 第二种优先权动态提升也适用于同属一个进程的线程,用以反应用户的输 入或磁盘的输入。例如,只要线程获得键盘输入,该线程就得到一个 +5 的优 先权调整值。
3> 那是在一个“等待状态”获得满足时发生的,例如有一个线程 正在等待一个 mu tex,当 Wait...() 返回时,该线程的优先权会获得动态提升。
4)更令人战栗的 Busy Waiting
改 变线程优先权可能会打开潘朵拉的盒子,一些新的问题跑出来,死锁的阴影也 潜在性地酝酿着。虽然优先权的基础知识很简单,但其实用面却可能很复杂。如果你的目标是保持简单,那就还是避免处理“优先权”这个烫手山芋吧。
3,初始化一个线程
1)如何初始化?
调用 CreateThread() ,新线程会如脱缰野马一下子就起跑了,你 根本来不及进行初始化设定操作。调用 CreateThread() ,新线程会如脱缰野马一下子就起跑了,你 根本来不及进行初始化设定操作。
hThread = CreateThread(NULL, 0, ThreadFunc, 0, CREATE_SUSPENDED, &threadId); SetThreadPriority(hThread, THREAD_PRIORITY_IDLE);
一旦线程设定妥当,你可以调用 Resum eThread() 开始执行:
DWORD ResumeThread( HANDLE hThread ); 参数 hThread 欲被再次执行的线程。 返回值 如果函数成功,则传回线程的前一个挂起次数。如果失败,则传回 0xFFFFFFFF。GetLastError() 可以获得更详细的信息。
2)挂起(suspending)一个线程
这个函数允许调用端指定一个线程睡眠(挂起)。直到又有人调用 了 Resum eThread(),线程才会醒来。因此,睡眠中的线程不可能唤醒自己。
DWORD SuspendThread( HANDLE hThread ); 参数 hThread 欲被挂起的线程。 返回值 如果函数成功,则传回线程目前的挂起次数。如果失败,则传回 0xFFFFFFFF。GetLastError() 可以获得更详细的信息。
SuspendThread() 是另一个可能会潜在引发问题的函数。考虑一下这种情 况:一个进程拥有三个线程A,B,C。线程C正在某个 critical section 内, 而线程B正在等它出来。然后,线程A挂起了线程C。在这种情况下,线程C 将永远不会离开 critical section,而线程B也就相当于进入了死锁状态。