zoukankan      html  css  js  c++  java
  • CreateWaitableTimer与SetWaitableTimer详解

    可等待定时器问题:

    1. 需要的函数:CreateWaitableTimer,SetWaitableTimer.前者创建一个可等待定时器句柄,后者设置等待定时器触发的条件.我们可以多次调用SetWaitableTimer来重置可等待定时器.重置后之前的定时器将关闭.

    2. 主要看两段代码:

    代码一:(这段代码在网上出现的概率是较大的)

    1. HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL ); 
    2.  
    3. LARGE_INTEGER li; 
    4.  
    5. li.QuadPart = 0; 
    6.  
    7.  
    8. if( !SetWaitableTimer( hTimer,&li,1000,NULL,NULL,FALSE )) 
    9.  
    10.  
    11. CloseHandle( hTimer ); 
    12.  
    13. return
    14.  
    15.  
    16. while ( 1 ) 
    17.  
    18.  
    19. //clock_t c_beg = clock();  
    20.  
    21. WaitForSingleObject( hTimer,INFINITE ); 
    22.  
    23. //clock_t end = clock() - c_beg;  
    24.  
    25. //cout<<"time:"<<end<<endl;  
    26.  
    27. cout<<"定时器触发了...\n"
    28.  
    29.  
    30. CloseHandle(hTimer); 
    HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL );
    
    LARGE_INTEGER li;
    
    li.QuadPart = 0;
    
    
    if( !SetWaitableTimer( hTimer,&li,1000,NULL,NULL,FALSE ))
    
    {
    
    CloseHandle( hTimer );
    
    return;
    
    }
    
    while ( 1 )
    
    {
    
    //clock_t c_beg = clock();
    
    WaitForSingleObject( hTimer,INFINITE );
    
    //clock_t end = clock() - c_beg;
    
    //cout<<"time:"<<end<<endl;
    
    cout<<"定时器触发了...\n";
    
    }
    
    CloseHandle(hTimer);
    
    

    通过将上面注释的代码放开,我们可以发现:

    ◆ 前两个定时器出发过程”不稳定”(即它们所耗费的时间并不是1.

    ◆ 就算是稳定了以后,定时器的差距并不是1s而是1000(毫秒)左右,这就奇怪了.

    如果说第二个问题是由于执行clock而产生的误差的话,那么第一个问题则没办法解释.(其实对于clock的时间几乎是可以忽略不计的.)

    这样就引入了核心编程里面作者的代码:

    代码二:

    1. HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL ); 
    2.  
    3. LARGE_INTEGER li; 
    4.  
    5. li.QuadPart = 0; 
    6.  
    7.  
    8. if( !SetWaitableTimer( hTimer,&li,1000,NULL,NULL,FALSE )) 
    9.  
    10.  
    11. CloseHandle( hTimer ); 
    12.  
    13. return
    14.  
    15.  
    16.  
    17. while ( 1 ) 
    18.  
    19.  
    20. clock_t c_beg = clock(); 
    21.  
    22. SleepEx( 1000,TRUE );//这里并没有使用WaitForSingleObject,而是使用SleepEx  
    23.  
    24. clock_t end = clock() - c_beg; 
    25.  
    26. cout<<"time:"<<end<<endl; 
    27.  
    28.  
    29. CloseHandle(hTimer); 
    HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL );
    
    LARGE_INTEGER li;
    
    li.QuadPart = 0;
    
    
    if( !SetWaitableTimer( hTimer,&li,1000,NULL,NULL,FALSE ))
    
    {
    
    CloseHandle( hTimer );
    
    return;
    
    }
    
    
    while ( 1 )
    
    {
    
    clock_t c_beg = clock();
    
    SleepEx( 1000,TRUE );//这里并没有使用WaitForSingleObject,而是使用SleepEx
    
    clock_t end = clock() - c_beg;
    
    cout<<"time:"<<end<<endl;
    
    }
    
    CloseHandle(hTimer);
    
    

    运行结果发现正常:每次都是1000(毫秒).

    从这里可以间接证明,clock消耗的时间可以忽略不计.

    再来看看SleepEx是怎么定义的.

    DWORD WINAPI SleepEx(

        DWORD dwMillesconds,

        BOOL bAlertable);

    这里主要说明第二个参数的用途:线程是否将自己置为可提醒状态.(在可提醒I/O中,当I/O完成时,系统将他们添加到线程APC队列中-回调函数不会立即被调用.如果我们想让其被调用需要将这个参数设置为TRUE).

    本例并没有牵涉到这类问题,所以无论FALSE或者TRUE都无所谓.

    如果我们只想要定义一个一次性定时器.可以参考如下代码:

    1. HANDLE hTimer = NULL; 
    2.  
    3. LARGE_INTEGER liDueTime; 
    4.  
    5.   liDueTime.QuadPart = -100000000;//10s  
    6.  
    7. hTimer = CreateWaitableTimer(NULL, TRUE,NULL); 
    8.  
    9.     if ( hTimer == NULL ) return
    10.  
    11.     if (!SetWaitableTimer(hTimer, &liDueTime, 1000, NULL, NULL, 0)) 
    12.  
    13.     {  
    14.  
    15. CloseHandle(hTimer); 
    16.  
    17.         return
    18.  
    19.  
    20. clock_t c_beg = clock(); 
    21.  
    22. if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0) 
    23.  
    24.  
    25. CloseHandle(hTimer); 
    26.  
    27. return
    28.  
    29.  
    30. else 
    31.  
    32.  
    33. //操作  
    34.  
    35.  
    36. CloseHandle(hTimer); 
    HANDLE hTimer = NULL;
    
    LARGE_INTEGER liDueTime;
    
      liDueTime.QuadPart = -100000000;//10s
    
    hTimer = CreateWaitableTimer(NULL, TRUE,NULL);
    
        if ( hTimer == NULL ) return;
    
        if (!SetWaitableTimer(hTimer, &liDueTime, 1000, NULL, NULL, 0))
    
        { 
    
    CloseHandle(hTimer);
    
            return;
    
    }
    
    clock_t c_beg = clock();
    
    if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0)
    
    {
    
    CloseHandle(hTimer);
    
    return ;
    
    }
    
    else
    
    {
    
    //操作
    
    }
    
    CloseHandle(hTimer);
    

    最后需要说明的一点是APC(异步调用过程)加入定时器中:

    1. VOID APIENTRY TimerAPCRoutine( PVOID pvArgToCompletionRoutine,DWORD dwTimerLowValue,DWORD dwTimerHighValue) 
    2.  
    3.  
    4. cout<<"high:"<<dwTimerHighValue<<"      low"<<dwTimerLowValue<<endl; 
    5.  
    6.  
    7. void main() 
    8.  
    9.  
    10. HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL ); 
    11.  
    12. LARGE_INTEGER li; 
    13.  
    14. li.QuadPart = 0; 
    15.  
    16.  
    17. if( !SetWaitableTimer( hTimer,&li,1000,TimerAPCRoutine,NULL,FALSE )) 
    18.  
    19.  
    20. CloseHandle( hTimer ); 
    21.  
    22. return
    23.  
    24.  
    25.  
    26. while ( 1 ) 
    27.  
    28.  
    29. SleepEx( 1000,TRUE ); 
    30.  
    31.  
    32. CloseHandle( hTimer ); 
    33.  
    34. getchar(); 
    35.  
    VOID APIENTRY TimerAPCRoutine( PVOID pvArgToCompletionRoutine,DWORD dwTimerLowValue,DWORD dwTimerHighValue)
    
    {
    
    cout<<"high:"<<dwTimerHighValue<<"      low"<<dwTimerLowValue<<endl;
    
    }
    
    void main()
    
    {
    
    HANDLE hTimer = CreateWaitableTimer( NULL,FALSE,NULL );
    
    LARGE_INTEGER li;
    
    li.QuadPart = 0;
    
    
    if( !SetWaitableTimer( hTimer,&li,1000,TimerAPCRoutine,NULL,FALSE ))
    
    {
    
    CloseHandle( hTimer );
    
    return;
    
    }
    
    
    while ( 1 )
    
    {
    
    SleepEx( 1000,TRUE );
    
    }
    
    CloseHandle( hTimer );
    
    getchar();
    
    }
    
  • 相关阅读:
    软件测试的定义及分类总结
    Selenium下拉菜单(Select)的操作Selenium快速入门(五)
    Selenium框架切换Selenium快速入门(七)
    元素(WebElement)Selenium快速入门(三)
    Selenium窗口切换Selenium快速入门(六)
    Selenium简介与环境搭配Selenium快速入门(一)
    测试用例的几种常见设计方法
    driver.get()和driver.navigate().to()到底有什么不同?Selenium快速入门(四)
    元素定位Selenium快速入门(二)
    关于VS2010与SQL Server2008 R2的安装问题
  • 原文地址:https://www.cnblogs.com/lidabo/p/3064910.html
Copyright © 2011-2022 走看看