Windows核心编程(笔记10) 第十一章 Windows线程池 第十二章 纤程

第十一章 Windows线程池

  1.Windows默认提供的线程池允许我们做四种事:(注:前提是系统会在必要的时候为进程创建一个默认的线程池,内部算法及怎么调度无需用户关心;若想指定自定制Windows线程池,可通过如下四种情况的CreateThreadpool*函数传入参数PTP_CALL_BACK_ENVIRON来实现)

    ①.以异步方式调用函数:通过TrySubmitThreadpoolCallback传入要调用的回调函数即可,此时系统内部会以我们的名义分配一个工作项,执行单位便是该工作项。若需要显示的创建并提交工作项可用:CreateThreadpoolWork创建一个绑定回调函数地址的工作项,再用SubmitThreadpoolWork传入该工作项参数来决定何时提交给线程池。若想取消已经提交的工作项可用WaitForThreadpoolWorkCallbacks,注意该函数的第二个参数,若为TRUE,则将判断该请求是否正在执行,在等待执行的话,则将其标记为取消,以告诉线程池无需执行,然后立即返回;正在执行的话,则等待直到其处理完成;若为FALSE,则会将调用线程挂起,直到该工作项处理完成且线程池中处理该工作项的线程准备好处理下一个工作项为止。删除工作项用CloseThreadpoolWork。

    ②.每隔一段时间调用一个函数:通过CreateThreadpoolTimer创建一个计时器对象,再用SetThreadpoolTimer注册计时器并指明工作方式。注意SetThreadpoolTimer,其参数pftDueTime:其以负值来指定一个相对时间,若为-1则表示立即开始,若为NULL则暂停计时器,正值则为绝对时间,以100ns为单位,从1600年的1月1日开始计算。参数msPeriod表示频率,单位为微秒,若为0则表示为一次性计时器。参数msWindowLength表示回调函数会在(当前设定的触发时间)到(当前设定的触发时间 += msWindowLength)之间的时间段内随机触发;可用来将一些触发频度近的计时器的触发时间段设定为存在交集,来让线程池对两个计时器进行批处理,即只唤醒一个线程来对两个计时器的回调函数分别处理,这样可提高效率。等待一个计时器完成和销毁计时器则用WaitForThreadpoolTimerCallbacks和CloseThreadpoolTimer,具体操作和①一样。

    ③.在内核对象触发时调用一个函数:通过CreateThreadpoolWait来创建一个线程池等待项,通过SetThreadpoolWait将其绑定到线程池。注意SetThreadpoolWait的参数pftTimeout:0表示不用等待,负值为相对时间,正值为绝对时间,NULL表示无限长时间(这儿NULL和0不是一回事)。等待项触发一次后,需要重新SetThreadpoolWait再次注册方可使用。若SetThreadpoolWait的参数hOject为NULL,则表示将该等待项从线程池中移除。注意:当线程池在等待传给SetThreadpoolWait的句柄时,必须确保该句柄不被关闭。同样的,等待一个等待项完成和销毁等待项用WaitForThreadpoolWaitCallbacks和CloseThreadpoolWait,具体操作和①一样。

    ④.在异步I/O请求完成时调用一个函数:通过CreateThreadpoolIo来创建一个线程池I/O对象,并将要关联的设备句柄传入,再通过StartThreadpoolIo来将设备句柄与线程池内部的I/O完成端口关联起来。注意:在调用ReadFile和WriteFile这俩之前调用StartThreadpoolIo,才能使起生效。CancelThreadpoolIo用来通知线程池停止调用回调函数,该操作与否不受ReadFile和WriteFile成功与否的影响。若需等待一个待处理的I/O请求完成,则用WaitForThreadpoolCallbacks,注意第二个参数bCancelPendingCallbacks;若解除该对象与线程池的关联则用CloseThreadpoolIo。

  2.可以让回调函数在返回之后执行一些额外的操作,实现方式为:在回调函数中,用传给它的不透明的pInstance参数(PTP_CALLBACK_INSTANCE类型)来调用某个函数(p339)。该操作的便利之处在于处理一些类似于:希望让回调函数能封装性的处理一些任务但又不想因环境因素影响的操作。比如蒋晟大神语:比如你的线程执行中碰到了堆栈溢出,这时候你不能调用LeaveCriticalSection这样有参数的函数,因为参数入不了栈。(有理啊~!)

  3.对线程进行定制:默认情况下,上述四种都是在系统为进程默认创建的线程池中进行的,若想使用自己定制的Windows线程池,可以:先通过CreateThreadpool创建线程池,再SetThreadpoolThreadMinimum/SetThreadpoolThreadMaxmum来指定线程池中最大最小线程数,再初始化回调环境InitializeThreadpoolEnvironment,并通过SetThreadpoolCallbackPool(回调环境,线程池)指明用该回调环境添加的工作项由哪个线程池来处理。这样,就可以通过指定该回调环境来用自定义的线程池了(通过CreateThreadpool*系函数中的PTP_CALLBAK_ENVIRON参数传入即可)。  另外,调用SetThreadpoolCallbackRunsLong和SetThreadpoolCallbackLibrary等可对该回调环境进行配置。 回调环境和线程池的销毁分别用DestroyThreadpoolEnvironment和CloseThreadpool,但是是在清理组清理完成后调用。(Windows开发组的人啊,这帮子接口的命名和处理方式能不能统一点啊!我非得写什么都得翻你MSDN么?)

  4.注意:自定线程池会有个小问题:线程池的内部算法决定了当该线程池认为创建或销毁某线程有助于提高性能的话,它就会这么做,这意味着如果在线程池中某线程上注册了一个需要监听或通知的事件,而该线程却被终止了,那么该事件将无法通知或监听到了。解决这个问题的办法是将线程池的最大和最小线程数设为相同,这样的话线程池会创建一组线程,且这些线程永远都不会销毁。

  5.为了帮助用户得体的销毁线程池,线程池提供了清理组。注:默认线程池不会被它销毁,默认线程池的生命周期和进程一样,在进程终止时,由系统清理。清理组由CreateThreadpoolCleanupGroup创建,然后通过SetThreadpoolCallbackCleanupGroup将其与绑定到线程池的回调环境关联起来,再调用CloseThreadpoolCleanupGroupMembers销毁线程池(注意它的参数bCancelPendingCallbacks,为TRUE时会对每一个被取消的工作项调用回调函数,该回调函数通过SetThreadpoolCallbackCleanupGroup的参数pfng指定,该回调函数的参数即当前调用函数的参数pvCleanipContext;为FALSE时,该函数返回之前线程池会花时间处理队列中所有的项,但此时不会调用回调函数,所以参数pvCleanupContext可以传NULL。) ,线程池销毁后再通过CloseThreadpoolCleanupGroup来释放清理组所占用的资源,最后调用DestroyThreadpoolEnvironment和CloseThreadpool。这样,就得体的干掉了线程池。-----(你敢再绕点啵?)

  6.注意个细节:对通过回调环境与自定线程池绑定的那些对象(工作项等)调用CloseThreadpool系列函数时,其实是隐式的将对应的项从清理组中移除。

  

 第十二章 纤程  (本章从略)

  1.纤程是为了让UNIX服务器中的多线程模拟机制移植到Windows平台而存在的。

  2.纤程是依附在线程里的代码片段,但拥有自己的执行上下文的内存地址。

  3.纤程函数不能返回,一旦返回那么该线程以及为它创建的所有纤程都将立即被销毁。

  4.一个线程同一时间只能执行一个纤程,所以纤程间的切换SwitchToFiber是线程级别的,会受线程调度的影响。并且SwitchToFiber是纤程获得CPU时间的唯一方法。

  5.纤程局部存储区:FLS,线程局部存储区:TLS。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值