设为首页 加入收藏

TOP

第三章--Win32程序的执行单元(部分概念及代码讲解)(上 -- 多线程)(一)
2017-10-12 10:11:57 】 浏览:4168
Tags:第三章 --Win32 程序 执行 单元 部分 念及 代码 讲解 线程

学习《Windows程序设计》记录

概念贴士:

1.  线程描述了进程内代码的执行路径。

 

2.  _stdcall是新标准C/C++函数的调用方法。从底层来说,使用这种调用方法参数的进栈顺序和标准C调用(_cdecl方法)是一样的,但是_stdcall采用自动清栈的方式,而_cdecl采用的是手动清栈方式。

 

3.  Windows规定,凡是由其负责调用的函数一律定义为_stdcall类型。ThreadProc是一个回调函数,即有Windows系统负责调用的函数,所以该函数应定义为_stdcall类型。另外,当没有显式说明时,函数默认的调用方法是_cdecl。

 

4.  创建新线程的函数是CreateThread,由这个函数创建的线程将在调用者的虚拟地址空间内执行。该函数执行成功后,将返回新建线程的线程句柄。

 

5.  WaitForSingleObject函数用于等待指定的对象(hHandle)变成受信状态。其中参数dwMilliseconds给出了以毫秒为单位的要等待时间。当其值为INFINITE时,表示要等待无限长时间。

  PS:  WaitForSingleObject(

                  hThread,    //要等待对象的句柄

                  INFINITE    //要等待的时间(以毫秒为单位)

                );

 

6.  当发生以下情况时,WaitForSingleObject函数就会返回:

    1)要等待的对象变成受信(signaled)状态;

    2)参数dwMilliseconds指定的时间已过去了。

  PS:一个可执行对象有两种状态,未受信(nonsignaled)和受信(signaled)状态。线程对象只有当线程运行结束时才达到受信状态。

 

7.  当创建子进程时,如果为CreateProcess函数的bInheritHandles参数传递TRUE,那么子进程就可以继承父进程的可继承句柄。

 

8.  dwCreationFlags--创建标志。如果为0,表示线程被创建后立即开始执行,如果指定为CREATE_SUSPENDED标志,表示线程被创建后处于挂起状态,即暂停状态,知道使用ResumeThread函数显式地启动该线程为止。

 

9.  线程内核对象可以说是一个包含了线程状态信息的数据结构。系统提供的管理线程的函数其实就是依靠访问线程内核对象来实现管理的。

     图表:    CONTEXT(上下文,即寄存器的状态)

                  EAX

                  EBX

                其他CPU寄存器

            Usage Count  使用计数(2)

            Suspend Count  暂停次数(1)

            Exi Code  退出代码(STILL_ACTIVE)

            Signaled  是否受信(FALSE)

            ...  ...  ...  ...

 

10.  线程上下文:每个线程都有着他自己的一组CPU寄存器,称为线程的上下文。

 

11.  使用次数:Usage Count成员记录了线程内核对象的使用次数,这个计数说明了此内核对象被打开的次数。只要线程没有结束运行,那么这个计数的值至少为1。在创建一个新的线程是,CreateThread函数返回了线程内核对象的句柄,相当于打开一次新创建的内核对象,这也会促使Usage Count的值加1。所以创建一个新的进程后,初始状态下Usage Count的值为2。之后,只要有进程打开这个内核对象,就会使得Usage Count的值加1。由于OpenThread函数的调用会灵Usage Count的值加1,所以在用完它们返回的句柄后一定要用CloseHandle函数进行关闭。(不关闭句柄,会造成内存泄漏。当然线程所在的进程结束后,该进程占用的所有资源都会统一释放。)线程函数一旦返回,线程的生命周期就到此为止。

 

12.  暂停次数:线程内核对象中的Suspend Count用于指明线程的暂停次数。创建线程的时候指定CREATE_SUSPENDED标志,就可以在线程有机会在执行任何代码之前改变线程的运行环境。(如优先级。)ResumeThread函数(唤醒一个被挂起的线程)会减少线程的暂停次数。注意,一个线程可以被暂停若干次。如果一个线程被暂停了3次,它必须被唤醒3次才可以分配给一个CPU。任何线程都可以调用SuspendThread函数来暂停另一个线程的运行。该函数可以增加线程的暂停次数。

 

13.  退出代码:成员Exit Code指定了线程的退出代码,也可以说是线程函数的返回值。同时也可以用GetExitCodeThread函数来获取线程的退出代码。

 

14.  是否受信:成员Signaled指定了线程对象是否为“受信”状态。线程在运行期间,Signaled的值永远是FALSE,即“未受信”。只有当线程结束后,系统才会把Signaled的值置为TRUE。

 

15.  线程的终止:当线程正常终止时,会发生下列事件:

      1)在线程函数中创建的所有C++对象将通过它们各自的析构函数被正确地销毁。

      2)该线程使用的堆栈将被释放。

      3)系统将线程内核对象中Exit Code(退出代码)的值由STELL_ACTIVE设置为线程函数的返回值。

      4)系统将递减线程内核对象中Usage Code(使用计数)的值。

 

16.  终止线程的执行有四种方法。

      1)线程函数自然退出。当函数执行到return语句返回时,Windows将终止线程的执行。建议使用这种方法终止线程的执行。

      2)使用ExitThread函数来终止线程。该函数会中止当前线程的进行,促使系统释放所有该线程使用的资源,但C/C++资源却不能得到正确的清楚。这里有一个有关析构函数的例子,就不展示了。

      3)使用TerminateThread函数在一个线程中强制终止另一个线程的执行。注意,这是被强烈建议避免的函数。因为一旦执行这个函数,程序将无法预测目标线程在何处被终止,这造成目标线程可能根本没有机会来做清除工作,如打开文件占用的内存等都不会被释放。另外,使用该函数终止进程的时候,系统不会释放线程使用的堆栈。

      4)使用ExitProcess函数来终止进程,系统会自动结束进程中所有线程的运行。但是这种方法相当于对每一个线程使用了TerminateThread函数,所以同样强烈建议避免。

      PS:每一个线程都应该让它正常退出,即由它的线程函数返回。通知线程退出有很多方法,如使用事件对象、设置全局变量等。

 

17.  线程的优先级:每个线程都要赋予一个优先级号,取值从0(最低)到31(最高)。

 

18.  Windows支持6个优先级类:idle、below normal、normal、above normal、high和real-time。进程属于一个优先级类,还可以为进程内的线程赋予一个相对线程优先级。线程刚被创建时,它的相对优先级总是被设置为normal。(表示解压文件时我修改了进程优先级,没感觉速度加快了啊。忧伤。)

 

19.  SetThreadPriority(HANDLE hThread, int nPriority)函数用去设置线程优先级。参数中前者是目标线程句柄,后者定义了线程的优先级。(后面会有相关优先级例子的展

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇中国大学MOOC-陈越、何钦铭-数据.. 下一篇C语言-预估校正法求常微分方程

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目