Win32 API 常用函数之一

 【线程】
       创建线程的函数是CreateThread,其原型如下:
HANDLE WINAPI CreateThread
(
  LPSECURITY_ATTRIBUTES lpThreadAttributes, 
  SIZE_T dwStackSize,
  LPTHREAD_START_ROUTINE lpStartAddress,
  LPVOID lpParameter,
  DWORD dwCreationFlags,
  LPDWORD lpThreadId
);
       参数说明:
    1. 第一个参数关于安全性,通常值为NULL。Windows会设置为默认安全级别。
    2. 第二个参数关于堆栈大小,(关于线程的堆栈,以后有机会一定仔细学习)对于简单应用,同安全性相同,使用默认的大小即可,一般传入0。
    3. 第三个参数是线程函数名,用于指明想要新线程执行的线程函数的地址。线程函数可以使用任何名字。实际上,如果在应用程序中拥有多个线程函数,必须为它们赋予不同的名字,否则编译器/链接程序会认为你为单个函数创建了多个实现函数。
    4. 第四个参数是线程函数的传入参数,在线程启动执行时将该参数传递给线程函数。该参数提供了一个将初始化值传递给线程函数的手段。该初始化数据既可以是数字值,也可以是指向包含其他信息的一个数据结构的指针。
    5. 第五个参数是设定用于控制创建线程的其他标志。它可以是两个值中的一个。如果该值是0,那么线程创建后可以立即进行调度。如果该值是CREATE_SUSPENDED,系统可以完整地创建线程并对它进行初始化,但是要暂停该线程的运行,这样它就无法进行调度。
    6. 第六个参数是线程的ID,当传入NULL时,表示并不关心线程的ID。
    7. 返回值:线程函数必须返回一个值,它将成为该线程的退出代码。
             线程函数(实际上是你的所有函数)应该尽可能使用函数参数和局部变量。当使用静态变量和全局变量时,多个线程可以同时访问这些变量,这可能破坏变量的内容。然而,参数和局部变量是在线程堆栈中创建的,因此它们不太可能被另一个线程破坏。
             在实际coding中,根据线程的作用,可以把线程封装在一个类里,如果需要让线程唯一,那么线程函数应该为static的;如果想让线程不唯一,那么就需要以成员函数的形式传入。不论上述两种情况的哪一种,都可以让第四个参数传入this,这样做比较方便。
             如果线程能够返回,就可以确保下列事项的实现:
        1. 在线程函数中创建的所有C + +对象均将通过它们的撤消函数正确地撤消。
        2. 操作系统将正确地释放线程堆栈使用的内存。
        3. 系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值。
        4. 系统将递减线程内核对象的使用计数。
                 ExitThread和TerminateThread都可以作为线程退出的函数,不过区别明显:
                 ExitThread函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C++资源(如C++类对象)将不被撤消。
                 TerminateThread函数终止线程时,会造成如下结果:不会对关键代码段对象进行操作,也就是说,如果线程中存在关键代码段,那他不会被销毁。分配的资源也不会从堆中撤销。线程状态被设置成inconsistent。当线程终止运行时,DLL通常接收通知。但使用TerminateThread 强迫线程终止,DLL就不接收通知。

          【关键代码段】
                 CRITICAL_SECTION 变量被用于控制多线程访问共享区的互斥行为。
                 在使用关键代码段之前,要对 CRITICAL_SECTION进行初始化,调用Initialize函数,需要使用互斥时调用Enter函数,结束互斥行为时使用Leave函数,销毁变量时使用Delete函数,原型如下:
          void  InitializeCriticalSection( 
            LPCRITICAL_SECTION lpCriticalSection 
          ); 
          void  EnterCriticalSection( 
            LPCRITICAL_SECTION lpCriticalSection 
          ); 
          void  LeaveCriticalSection( 
            LPCRITICAL_SECTION lpCriticalSection 
          ); 
          void  DeleteCriticalSection( 
            LPCRITICAL_SECTION lpCriticalSection 
          ); 
              EnterCriticalSection 函数负责查看该结构中的成员变量。这些变量用于指明当前是哪个变量正在访问该资源。如果成员变量指明,调用线程已经被赋予对资源的访问权,那么 EnterCriticalSection 便更新这些变量,以指明调用线程多少次被赋予访问权并立即返回,使该线程能够继续运行。
              如果成员变量指明,一个线程(除了调用线程之外)已被赋予对资源的访问权,那么
          EnterCriticalSection 将调用线程置于等待状态。这种等待的线程不会浪费任何CPU时间。系统能够记住该线程想要访问该资源并且自动更新 CRITICAL_SECTION 的成员变量,一旦目前访问该资源的线程调用 LeaveCriticalSection 函数,该线程就处于可调度状态。
             
          LeaveCriticalSection 要查看该结构中的成员变量。该函数每次计数时要递减1,以指明调用线程多少次被赋予对共享资源的访问权。如果该计数大于0,那么 LeaveCriticalSection 不做其他
          任何操作,只是返回而已。如果该计数变为0,它就要查看在调用
          EnterCriticalSection 中是否有别的线程正在等待。如果至少有一个线程正在等待,它就更新成员变量,并使等待线程中的一个线程(“公正地”选定)再次处于可调度状态。如果没有线程正在等待, LeaveCriticalSection 函数就更新成员变量,以指明没有线程正在访问该资源。
              如果不想等,想得到要么能够使用资源,要么去做别的事情的方法,就用Try
          EnterCriticalSection,当能够使用资源时,该函数返回TRUE,不能时返回FALSE。他不会把自己加入等待队列中去。

              使用关键代码段时有一些技巧:
            1. 每个共享资源使用一个CRITICAL_SECTION变量,如果应用程序中拥有若干个互不相干的数据结构,应该为每个数据结构创建一个CRITICAL_SECTION变量。这比只有单个CRITICAL_SECTION结构来保护对所有共享资源的访问要好(效率高)。
            2. 当同时访问多个资源时,必须始终按照完全相同的顺序请求对资源的访问。
            3. 不要长时间运行关键代码段,当一个关键代码段长时间运行时,其他线程就会进入等待状态,这会降低应用程序的运行性能。




              评论
              添加红包

              请填写红包祝福语或标题

              红包个数最小为10个

              红包金额最低5元

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

              抵扣说明:

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

              余额充值