当前位置:松语文学 > 其他类型 >VC++_6.0程序设计从入门到精通最新章节 > VC++_6.0程序设计从入门到精通TXT下载
错误举报

第 46 章

  xitThread

  结束线程最直观的方法是调用Win32API 函数ExitThread,线程执行完线程函数的代码

  后,会隐式调用ExitThread 函数,自动终止。当调用该函数时,当前线程的堆栈被释放,如

  果当前线程是进程的最后一个线程,则进程也终止。它的函数原型如下。

  VOID ExitThread(

  DWORD dwExitCode

  );

  函数中主要参数的意义如下。

  ? dwExitCode:线程的返回码。

  2.Win32API 函数TerminateThread

  TerminateThread 用于强行终止一个线程。如果调用成功,返回TRUE,否则返回FALSE。

  它的函数原型如下:

  BOOL TerminateThread(

  HANDLE hThread,

  DWORD dwExitCode

  );

  函数中主要参数的意义如下。

  ? hThread:要终止的线程句柄。

  ? dwExitCode:线程的终止码,可以调用函数GetExitCodeThread 来得到。

  函数GetExitCodeThread 用于得到线程的退出码,如果调用成功,返回TRUE,否则返回

  FALSE。它的函数原型如下:

  BOOL GetExitCodeThread(

  HANDLE hThread,

  LPDWORD lpExitCode

  );

  函数中主要参数的意义如下。

  ? hThread:要终止的线程句柄。

  ? LpExitCode:存放线程终止状态的变量指针。

  枫叶文学网www.fywxw.com

  Visual C++ 6.0 程序设计从入门到精通

  ·212·

  3.C 运行库函数

  C 运行库函数包括_endthread 和_endthreadex,分别用来结束一个由_beginthread 或

  _beginthreadex 创建的线程。函数原型如下。需要注意的是,与ExitThread 相同,_endthreadex

  并不关闭线程的句柄,因此,当调用这个函数之前,必须首先调用Win32 API 函数

  CloseHandle。

  void _endthread( void );

  void _endthreadex(

  unsigned retval

  );

  函数中主要参数的意义如下。

  ? retval:线程返回码。

  4.函数AfxEndThread

  函数AfxEndThread 用来终止由AfxBeginThread 创建的线程,它没有返回值,函数原型

  如下:

  void AFXAPI AfxEndThread(

  UINT nExitCode,

  BOOL bDelete = TRUE

  );

  函数中主要参数的意义如下。

  ? nExitCode:线程的返回码。

  ? bDelete:从内存中删除线程对象的标志。

  9.3.3 线程的管理和cāo作

  1.线程的挂起、继续和休眠

  (1)挂起

  如果一个正在执行的线程用完了自己的时间片,则这个线程将会被挂起,并将CPU 时间

  分给其他等待的线程。也可以通过调用Win32 API 函数SuspendThread 来挂起一个正在执行

  的线程,如果调用成功,返回线程上一次的挂起计数,否则返回-1。SuspendThread 的函数原

  型如下:

  DWORD SuspendThread(

  HANDLE hThread

  );

  函数中主要参数的意义如下。

  ? hThread:线程的句柄。

  MFC 将线程cāo作进行了封装,CWinThread 的对象可以调用它的成员函数SuspendThread

  来挂起一个正在执行的线程。

  枫叶文学网www.fywxw.com

  第9 章 多线程

  ·213·

  (2)继续

  如果继续执行SuspendThread 挂起的线程,或者在执行时采用CREATE_SUSPENDED 标

  记创建的线程,可以调用函数RescomThread,将当前被挂起的线程的挂起计数减一。如果一

  个线程的挂起计数减为0,则线程开始继续执行。如果调用成功,返回线程上一次的挂起计

  数,否则返回0xFFFFFFFF。如果返回值为0,则说明当前线程并没有挂起。如果返回1,说

  明线程被挂起,现在开始继续执行。RescomThread 的函数原型如下:

  DWORD RescomThread( );

  (3)休眠

  函数Sleep 可以让当前执行的线程休眠一段时间,而函数SleepEx 将线程挂起,等待下

  列事件之一发生。

  ? 一个I/O 回调函数被调用。

  ? 线程需要调用一个异步的过程。

  ? 时间间隔到。

  它们的函数原型如下:

  VOID Sleep(

  DWORD dwMilliseconds

  );

  函数中主要参数的意义如下。

  ? dwMilliseconds:休眠时间。

  DWORD SleepEx(

  DWORD dwMilliseconds,

  BOOL bAlertable

  );

  函数中主要参数的意义如下。

  ? dwMilliseconds:超时间隔。

  ? bAlertable:指定函数是否依赖I/O 回调函数结束。

  如果指定的时间间隔期满,则返回0。如果函数返回依赖于一个或多个I/O 回调函数则

  返回WAIT_IO_COMPLETION,这种情况只有bAlertable 为TRUE 的时候才会发生。

  2.线程的优先级

  (1)级别

  Windows 允许用户在线程执行的过程中动态地得到或者改变线程的优先级,使重要的线

  程可以优先执行,占有较多的时间片。该过程可以通过调用Win32 API 函数SetThreadPriority

  来调整进程内的线程优先级,Win32 进程的优先级如表9-2 所示,线程的优先级如表9-3 所

  示。

  表9-2 进程优先级列表

  优先级 优先级值

  ABOVE_NORMAL_PRIORITY_CLASS

  大于NORMAL_PRIORITY_CLASS,

  小于HIGH_PRIORITY_CLASS

  枫叶文学网www.fywxw.com

  Visual C++ 6.0 程序设计从入门到精通

  ·214·

  续表

  优先级 优先级值

  BELOW_NORMAL_PRIORITY_CLASS

  大于IDLE_PRIORITY_CLASS,

  小于NORMAL_PRIORITY_CLASS.

  HIGH_PRIORITY_CLASS 13

  IDLE_PRIORITY_CLASS 4

  NORMAL_PRIORITY_CLASS 9(前台)或7(后台)

  REALTIME_PRIORITY_CLASS 24

  表9-3 线程优先级列表

  优先级 级别

  THREAD_PRIORITY_ABOVE_NORMAL 比进程优先级高一级

  THREAD_PRIORITY_BELOW_NORMAL 比进程优先级低一级

  THREAD_PRIORITY_HIGHEST 比进程优先级高两级

  THREAD_PRIORITY_LOWEST 比进程优先级低两级

  THREAD_PRIORITY_NORMAL 与进程优先级相同

  THREAD_PRIORITY_TIME_CRITICAL 把线程优先级设为15

  THREAD_PRIORITY_IDLE 把线程优先级设为1

  (2)优先级的设置和获取

  可以通过调用Win32 API 函数GetThreadPriority 或SetThreadPriority 实现或修改线程优先级

  的功能,如果调用成功,返回线程的优先级,否则返回THREAD_PRIORITY_ERROR_RETURN。

  GetThreadPriority 的函数原型如下:

  int GetThreadPriority(

  HANDLE hThread

  );

  函数中主要参数的意义如下。

  ? hThread:线程的局柄。

  函数SetThreadPriority 用来设定线程的优先级,如果调用成功,返回非0,否则返回0。

  它的函数原型如下:

  BOOL SetThreadPriority(

  HANDLE hThread,

  int nPriority

  );

  函数中主要参数的意义如下。

  ? hThread:线程的局柄;

  ? nPriority:要设定的优先级。

  在本节最后给出的示例中,读者可以看到如何利用SetThreadPriority 设定一个线程的优

  先级。

  3.线程ID 的判断

  在创建线程的同时,系统会为每个线程生成一个线程ID。任何两个线程ID 都不会相同。

  许多Win32 API 函数都以线程ID 作为参数对线程进行cāo作。在调用CreateThread 或者

  _begintread 创建线程的时候,会返回线程ID,可以在这个时候将ID 保存下来。调用Win32 API

  枫叶文学网www.fywxw.com

  第9 章 多线程

  ·215·

  函数GetCurrentThreadID 可以得到当前线程ID。该函数没有参数,它的函数原型如下:

  DWORD GetCurrentThreadId(VOID);

  用户也可以调用Win32 API 函数GetCurrentThread 得到当前线程的伪句柄,函数原型如

  下:

  HANDLE GetCurrentThread(VOID);

  4.线程的切换

  如果希望cāo作系统从当前正在执行的线程切换到其他就绪线程,可以通过调用Win32

  API 函数SwitchToThread 实现,切换后的线程由cāo作系统选择。SwitchToThread 函数没有参

  数,它的函数原型如下:

  BOOL SwitchToThread(VOID);

  5.打开线程

  Win32 API 函数OpenThread 可以打开一个存在的线程对象。如果调用成功,返回指定线

  程的句柄,否则返回NULL。它的函数原型如下:

  HANDLE OpenThread(

  DWORD dwDesiredAccess,

  BOOL bInheritHandle,

  DWORD dwThreadId

  );

  函数中主要参数的意义如下。

  ? dwDesiredAccess:描述希望对线程进行的访问。

  ? bInheritHandle:指定返回的句柄是否可以被一个当前进程创建的新进程继承。

  ? dwThreadId:被访问线程的ID。

  6.线程函数ThreadProc

  线程函数是一个由用户定义的函数,作为执行线程的入口。在调用创建线程函数的时候,

  将ThreadProc 作为参数传入。返回调用成功或失败的标记。它的函数原型如下:

  DWORD WINAPI ThreadProc(

  LPVOID lpParcomter

  );

  函数中主要参数的意义如下。

  ? lpParcomter:传给线程函数的参数。

  7.获得线程的时间信息

  线程的生命周期中,可以调用GetThreadTcoms 函数得到指定线程的时间信息。如果调用

  成功,返回非0 值,否则返回0。GetThreadTcoms 函数原型如下:

  BOOL GetThreadTcoms(

  HANDLE hThread,

  LPFILETIME lpCreationTcom,

  枫叶文学网www.fywxw.com

  Visual C++ 6.0 程序设计从入门到精通

  ·216·

  LPFILETIME lpExitTcom,

  LPFILETIME lpKernelTcom,

  LPFILETIME lpUserTcom

  );

  函数中主要参数的意义如下。

  ? hThread:线程的句柄。

  ? lpCreationTcom:保存线程的创建时间。

  ? lpExitTcom:保存线程的生存时间。

  ? lpKernelTcom:保存线程在内核模式下的生存时间。

  ? lpUserTcom:保存线程在用户模式下的执行时间。

  FILETIME是一个64 位数的结构,表示从1601 年1 月1 日到现在以十亿分之一为间隔

  的时间片数。它的定义如下:

  typedef struct _FILETIME {

  DWORD dwLowDateTcom;

  DWORD dwHighDateTcom;

  } FILETIME, *PFILETIME;

  结构中主要成员变量的意义。

  ? dwLowDateTcom:表示低32 位字节。

  ? dwHighDateTcom:表示高32 位字节。

  8.处理器相关cāo作

  (1)SetThreadAffinityMask 函数

  该函数用于为指定的线程设置其处理器相似xìng掩码。一个线程相似xìng掩码是一个位向

  量,每一位表示一个线程可以使用的处理器。线程相似xìng只对多处理器计算机有作用。对通

  常使用的单CPU 机器无效。如果调用成功,返回非0 值。否则返回0。

  SetThreadAffinityMask 函数原型入下:

  DWORD_PTR SetThreadAffinityMask (

  HANDLE hThread,

  DWORD_PTR dwThreadAffinityMask

  );

  松语文学免费小说阅读_www.16sy.com