windows下线程入门

windows线程

以下内容引述《windows核心编程》

线程与进程

进程实际上有两个组成部分:一个进程内核对象和一个地址空间;同样的,线程也有两个组成部分:

  1. 线程的内核对象,操作系统用它管理线程,系统还用内核对象来存放线程统计信息的地方;
  2. 线程栈,用于维护线程执行时所需的所有函数参数和局部变量

创建线程

对于用MSVC编译器生成的应用程序,这个线程首先会执行C/C++运行库的启动代码,后者调用入口点函数(_tmain或者_tWinMain),直入口点函数返回C/C++运行库的启动代码,后者最终将调用ExitProcess

HANDLE CreateThread(
	PSECURITY_ATTRIBUTES psa,
	DWORD cbStackSize,
	PTHREAD_START_ROUTINE pfnStartAddr,
	PVOID pvParam,
	DWORD dwCreateFlags,
	PDWORD pdwThreadId);

调用CreateThread是,系统会创建一个线程内核对象,该内核对象提供给操作系统用于管理线程。同时,系统从进程的地址空间中分配内存给线程栈使用。新线程与负责创建的那个线程在相同的进程上下文中运行。因此,新线程可以访问进程内核对象的所有句柄、进程中的所有内存以及同一个进程中其他所有线程的栈。

推荐使用_beginthreadex函数在C/C++编程中创建线程。

避免创建线程

在几乎所有的应用程序中,所有的用户界面组件(窗口)都应该共享同一个线程。一个窗口的所有子窗口无疑应该由一个线程来创建。有时,也许需要在不同的线程上创建不同的窗口,但这类情形相当少见。
通常,应用程序有一个用户界面线程,此线程负责创建所有窗口,另外还负责GetMessage循环。进程中的其他所有线程都是受计算机能力的制约或者受I/O(输出/输入)限制的工作线程,这些线程永远不会创建窗口。
用户界面线程的优先级永远高于工作线程。

进程与线程

线程内核对象的寿命至少可以达到他们相关联的线程那样长。不过,对象的寿命可能超过线程本身的寿命。

  1. 默认情况下,主线程的入口函数必须命名为main,wmain,WinMain或者wWinMain。但是线程函数可以随意命名;
  2. 进程的函数入参,提供了ANSI/Unicode版本供我们选择;而线程只有一个参数;
  3. 线程函数必须返回一个值,成为该线程的退出码;类似于C/C++运行库的策略:领主线程的退出代码成为进程的退出代码。
  4. 线程尽可能使用函数参数和局部变量。

线程终止

终止的方式

  1. 线程函数返回(推荐)
  2. 线程调用ExitThread函数“杀死”自己
  3. 同一个线程或另一个进程中的线程调用TerminateThread函数(避免)
  4. 包含线程的进程终止运行(避免)

其中1.线程函数返回的方式,是正确处理线程的唯一方式,可以确保一下正确的应用程序清理工作都可以执行

  • 线程函数中创建的所有C++对象都通过其析构函数被正确销毁
  • 操作系统正确释放线程栈使用的内存
  • 操作需提供把线程的退出代码(在线程的内核对象中维护)设为线程函数的返回值;
  • 系统递减线程的内核对象的使用计数

而2.调用ExitThread函数的方式,将终止线程的运行,并导致操作系统清理该线程使用的而所有操作系统资源。但是,C/C++资源(如C++类对象)不会被销毁。因为ExitThread函数和CreateThread函数一样,都是windows函数,并不是C/C++函数。使用_endthreadex替代ExitThread函数。

3.调用TerminateThread函数可以杀死一个线程,而不仅仅只有主调线程,TerminateThread可以杀死任意线程。该函数是异步的,需要调涌WaitForSingleObject或类似的函数,并向其传递线程的句柄。

ExitThread和TerminateThread的区别:
ExitThread函数终止线程的运行,该线程的堆栈也会被销毁;如果用TerminateThread,那么除非拥有此线程的进程终止运行,否则系统不会销毁这个线程的堆栈。
此外,动态链接库(DLL)通常会在线程终止运行时收到通知,不过,如果线程是用TerminateThread强行“杀死”的,那么DLL不会收到这个通知,结果是不能执行正常的清理工作。

进程终止和线程终止

进程终止,ExitProcess和TeminateProcess可用于终止线程运行,区别是这些函数会使终止运行的进程中的所有的线程全部终止。同时,由于整个进程都会关闭,所有的系统资源肯定会被清理。其中必然包括所有线程的堆栈。但是这样意味着正确的应用程序清理工作不会执行:c++对象的析构函数不会被调用,数据不会会写到磁盘……

线程终止:

  • 线程拥有的所有用户对象句柄被释放(windows中,大多数对象都是由包含了“创建这些对象的线程”的进程拥有的,但是一个线程有两个用户对象,窗口和钩子)。线程退出时,系统会自动销毁由线程创建或安装的任何窗口,并卸载由线程创建或安装的任何钩子。其他对象只有在拥有线程的进程终止时才会被销毁。
  • 线程的退出代码从STILL_ACTIVE变成传给ExitThread或者TerminateThread
  • 线程的内核对象的状态变成触发状态
  • 如果线程是进程中的最后一个活动对象,系统认为进程也终止了
  • 线程内核对象的引用计数-1
    其他线程调用GetExitCodeThread来检查hThread所标识的那个线程是否终止运行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值