zoukankan      html  css  js  c++  java
  • 线程通信机制之定时器队列

    线程通信机制之定时器队列

    ——每周杂谈 第008篇

    作者:Tocy    时间:2012-06-01

    关键词:定时器队列,ITC

    定时器队列(Timer Queue)可以使用CreateTimerQueue函数创建。定时器队列中的定时器是轻量级对象,可以在一定时间间隔之后调用指定的回调函数(可以只调用一次,也可以是周期性的)。这种等待操作由线程池中某个线程处理的(系统级别)。

    向定时器队列中添加定时器可以使用CreateTimerQueueTimer函数。更新一个计时器队列中的计时器可以使用 ChangeTimerQueueTimer 函数。这两个函数中你可以指定一个回调函数,如果设定时间到达,线程池中某个线程会调用该回调函数。

    使用 DeleteTimerQueueTimer函数可以取消挂起的计时器。当不再使计时器队列的时候,调用 DeleteTimerQueueEx 函数删除计时器队列,该函数调用是会取消并删除任何在该队列中等待的计时器。

    MSDN链接:http://msdn.microsoft.com/en-us/library/ms686796(v=vs.85)

    使用例子如下:

    #include <windows.h>

    #include <stdio.h>

     

    HANDLE gDoneEvent;

     

    VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired)

    {

    if (lpParam == NULL)

    {

    printf("TimerRoutine lpParam is NULL\n");

    }

    else

    {

    // lpParam points to the argument; in this case it is an int

     

    printf("Timer routine called. Parameter is %d.\n",

    *(int*)lpParam);

    if(TimerOrWaitFired)

    {

    printf("The wait timed out.\n");

    }

    else

    {

    printf("The wait event was signaled.\n");

    }

    }

     

    SetEvent(gDoneEvent);

    }

     

    int main()

    {

    HANDLE hTimer = NULL;

    HANDLE hTimerQueue = NULL;

    int arg = 123;

     

    // Use an event object to track the TimerRoutine execution

    gDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    if (NULL == gDoneEvent)

    {

    printf("CreateEvent failed (%d)\n", GetLastError());

    return 1;

    }

     

    // Create the timer queue.

    hTimerQueue = CreateTimerQueue();

    if (NULL == hTimerQueue)

    {

    printf("CreateTimerQueue failed (%d)\n", GetLastError());

    return 2;

    }

     

    // Set a timer to call the timer routine in 10 seconds.

    if (!CreateTimerQueueTimer( &hTimer, hTimerQueue,

    (WAITORTIMERCALLBACK)TimerRoutine, &arg , 10000, 0, 0))

    {

    printf("CreateTimerQueueTimer failed (%d)\n", GetLastError());

    return 3;

    }

     

    // TODO: Do other useful work here

     

    printf("Call timer routine in 10 seconds...\n");

     

    // Wait for the timer-queue thread to complete using an event

    // object. The thread will signal the event at that time.

     

    if (WaitForSingleObject(gDoneEvent, INFINITE) != WAIT_OBJECT_0)

    printf("WaitForSingleObject failed (%d)\n", GetLastError());

     

    CloseHandle(gDoneEvent);

     

    // Delete all timers in the timer queue.

    if (!DeleteTimerQueue(hTimerQueue))

    printf("DeleteTimerQueue failed (%d)\n", GetLastError());

     

    return 0;

    }

    这段代码比较容易理解,这里不做详细解释了。功能很简单:利用定时器队列实现延时10s执行指定回调函数。

    比较有意思的是:CreateTimerQueueTimer函数。

    该函数功能是创建一个计时器队列中的计时器。原型如下:

    BOOL WINAPI CreateTimerQueueTimer(

    __out         PHANDLE phNewTimer,                //计时器句柄指针

    __in_opt      HANDLE TimerQueue,                //计时器队列句柄

    __in          WAITORTIMERCALLBACK Callback,        //回调函数指针

    __in_opt     PVOID Parameter,                    //传给回调函数的参数

    __in          DWORD DueTime,                    //到期时间(以毫秒为单位)

    __in          DWORD Period,                    //计时器周期(以毫秒为单位)

    __in          ULONG Flags                        //标志位,通常使用0

    );

    计时器在DueTime时间过后首次到期,然后按照给定的period时间间隔到期,每次到期都会调用回调函数。

    其参数中计时器队列指针可以为NULL(此时计时器与默认计时器队列关联)。period如果为0,计时器指signaled一次;如果大于0,计时器是周期性的,直到计时器被取消。

    Windows下的计时器有三类:Timer,timer queue,和waitable timer。从复杂度上而言,一次增加,功能也更加强大。Timer只能用在单独一个计时器处理函数或者WM_TIMER消息中,而timer queue可以提供更多更准确的计时方式(在线程池中运行,效率更高), waitable timer则是同步对象,可以用于多进程之间的通信。从功能上而言基本都是一致的,只有timer提供简单的周期执行(没有单次执行的计时器,当然可以实现这种计时器的)。

    所以如果需要使用timer (计时器)的话,最好从最简单的开始,如果性能不能满足要求,依次尝试timer、timer queue、waitable timer。

    注:版权所有,请勿用于商业用途,转载请注明原文地址。本人保留所有权利。

  • 相关阅读:
    【bzoj2190】: [SDOI2008]仪仗队 数论-欧拉函数
    【bzoj2751】[HAOI2012]容易题(easy) 数论-快速幂
    【bzoj2186】: [Sdoi2008]沙拉公主的困惑 数论-欧拉函数
    这里会有你想要的,已收录css , js相关文章
    Vue源码解析--实现一个指令解析器 Compile
    九宫格抽奖
    12行代码简单实现跑马灯文字匀速滚动
    滑弯曲弧形效果的插件-arctext.js改造
    几种拼图小游戏封装
    倒计时
  • 原文地址:https://www.cnblogs.com/tocy/p/2532562.html
Copyright © 2011-2022 走看看