APC的很好的解释

   通过异步程序调用(APC)实现的定时功能
    定时器是一个在特定时间或者规则间隔被激发的内核对象。
    结合定时器的异步程序调用可以允许回调函数在任何定时器被激发的时候执行。
    本文的例子代码显示了如何实现。
  使用本定时器时,你需要把常量_WIN32_WINNT定义为0x0400,并且此常量应该在包之前定义,以确保声明合适的定时器原型函数。
  通过调用CreateWaitableTimer()可以创建一个定时器,此函数返回一个指向内核对象的句柄。若定时器已经存在,
    你可以通过使用OpenWaitableTimer()获得一个进程相关的句柄。无论是通过CreateWaitableTimer() 还是通过OpenWaitableTimer()获得的句柄,在不需要定 时器时必须释放,方法是使用函数CloseHandle()。
  定时的时间通过调用SetWaitableTimer()来设置,可以设置为一个特定的时刻(如December 16, 1999 at 9:45 PM)或者一个相对的时间(如从现在起每五分钟)。函数SetWaitableTime()定时的时间参数要求LARGE_INTEGER类型。这个值应该符合在结构体FILETIME中描述的格式。如果值是正的,代表一个特定的时刻。如果值是负的,代表以100纳秒为单位的相对时间。后面的示例代码中使用的是相对时间。在调用SetWaitableTimer()函数后,定时器将在每5秒被激发一次。
  你也可以将定时器设置为周期性的自我激发
    ,方法是向SetWaitableTimer()的第三个参数传递一个周期参数(以毫秒为单位)。
    在CreateWaitableTimer()的第二个参数传递FALSE可以产生一个自动归零的定时器。本例设置周期为两秒的定时器。
  当设置了定时器之后,你就可以将APC与其结合起来。这里把APC函数称作完全例程。
    完全例程的地址作为SetWaitableTimer()的第四个参数。第五个参数是一个空类型的指针,
    你可以使用它来传递完全例程的参数。
  在所有的APC中,要执行一个完全例程则线程必须处于监听状态。完全例程将总是被调用SetWaitableTimer()的相同的线程执行
    ,所以此线程必须将必须其自身置于监听状态。可以调用下面的任何一个监听函数来完成监听状态的设置:
 SleepEx();
 WaitForSingleObjectEx();
 WaitForMultipleObjectsEx();
 MsgWaitForMultipleObjectsEx();
 SignalObjectAndWait();
  任何一个线程都有一个APC队列。在调用上面的任何一个函数时,如果线程的APC队列中有实体,则此线程不会进入休眠状态,
    取而代之要做的是将实体从APC队列中取出,然后调用相应的完全例程。
  如果在APC队列中不存在实体,那么线程将会被挂起,直至等待条件满足为止。
    满足等待条件的有:一个实体加入到APC队列中,超时,激活句柄等,
    以及在调用MsgWaitForMultipleObjectsEx()情况下,一个消息进入到线程的一个消息队列中。
    若等待条件满足的是APC队列中的一个实体,那么线程会被激活,并且执行完全例程,这种情况下的函数的返回值是 WAIT_IO_COMPLETION.

  【重要提示】

   1、在执行完一个完全例程之后,系统会检查在APC中剩下的实体以处理。一个监视函数仅仅在处理完所有APC实体后才返回。
   因此,如果实体加入到APC队列的速度比处理的更快的话,则调用这些函数可能永远也不能返回。
   特别当定时等待的时间比起要求执行完全例程的时间更短的话,这种情况更容易发生。
   2、当使用APC来实现定时器时,设置定时的线程不应该等待定时器的句柄。如果等待定时器的句柄的话,
   则唤起这个线程的原因是定时器被激活,而不是有实体加入到APC队列中。这时线程将不再处于监听状态,所以 完全例程也不会被调用。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值