Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4233311
  • 博文数量: 447
  • 博客积分: 1241
  • 博客等级: 中尉
  • 技术积分: 5786
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-27 06:48
个人简介

读好书,交益友

文章分类

全部博文(447)

文章存档

2024年(1)

2023年(5)

2022年(29)

2021年(49)

2020年(16)

2019年(15)

2018年(23)

2017年(67)

2016年(42)

2015年(51)

2014年(57)

2013年(52)

2012年(35)

2011年(5)

分类: C/C++

2014-12-30 17:51:39

可能是多线程程序写多了,单线程程序居然不会用了。
最近做一个ETL工具,有个功能就是每个5分钟检查一下数据库的状态,因为是console程序,无法使用WM_TIMER。
我经常使用CreateTimerQueueTimer,这次决定使用SetWaitableTimer单线程的。
看了一下msdn,简单修改了一下
// Waitable.cpp : 定义控制台应用程序的入口点。
//

点击(此处)折叠或打开

  1. #include "stdafx.h"
  2. #include <windows.h>
  3. #include <stdio.h>
  4. #include <tchar.h>

  5. #define _SECOND 10000000

  6. typedef struct _MYDATA {
  7.    TCHAR *szText;
  8.    DWORD dwValue;
  9. } MYDATA;
  10. HANDLE gDoneEvent;

  11. VOID CALLBACK TimerAPCProc(
  12.    LPVOID lpArg, // Data value
  13.    DWORD dwTimerLowValue, // Timer low value
  14.    DWORD dwTimerHighValue ) // Timer high value

  15. {
  16.    // Formal parameters not used in this example.
  17.    UNREFERENCED_PARAMETER(dwTimerLowValue);
  18.    UNREFERENCED_PARAMETER(dwTimerHighValue);

  19.    MYDATA *pMyData = (MYDATA *)lpArg;

  20.    _tprintf( TEXT("Message: %s\nValue: %d\n\n"), pMyData->szText,
  21.           pMyData->dwValue );
  22.    MessageBeep(0);

  23. }

  24. int _tmain(int argc, _TCHAR* argv[])
  25. {
  26.     HANDLE hTimer;
  27.    BOOL bSuccess;
  28.    __int64 qwDueTime;
  29.    LARGE_INTEGER liDueTime;
  30.    MYDATA MyData;

  31.    MyData.szText = TEXT("This is my data");
  32.    MyData.dwValue = 100;

  33.        // Use an event object to track the TimerRoutine execution
  34.     gDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  35.     if (NULL == gDoneEvent)
  36.     {
  37.         printf("CreateEvent failed (%d)\n", GetLastError());
  38.         return 1;
  39.     }


  40.    hTimer = CreateWaitableTimer(
  41.            NULL, // Default security attributes
  42.            FALSE, // Create auto-reset timer
  43.            TEXT("MyTimer")); // Name of waitable timer
  44.    if (hTimer != NULL)
  45.    {
  46.       __try
  47.       {
  48.          // Create an integer that will be used to signal the timer
  49.          // 5 seconds from now.
  50.          qwDueTime = -5 * _SECOND;

  51.          // Copy the relative time into a LARGE_INTEGER.
  52.          liDueTime.LowPart = (DWORD) ( qwDueTime & 0xFFFFFFFF );
  53.          liDueTime.HighPart = (LONG) ( qwDueTime >> 32 );

  54.          bSuccess = SetWaitableTimer(
  55.             hTimer, // Handle to the timer object
  56.             &liDueTime, // When timer will become signaled
  57.             2000, // Periodic timer interval of 2 seconds
  58.             TimerAPCProc, // Completion routine
  59.             &MyData, // Argument to the completion routine
  60.             FALSE ); // Do not restore a suspended system

  61.          if ( bSuccess )
  62.          {
  63.            /*
  64.              for ( ; MyData.dwValue < 1000; MyData.dwValue += 100 )
  65.             {
  66.                SleepEx(
  67.                   INFINITE, // Wait forever
  68.                   TRUE ); // Put thread in an alertable state
  69.             }
  70.             */
  71.              if (WaitForSingleObject(gDoneEvent, INFINITE) != WAIT_OBJECT_0)
  72.          printf("WaitForSingleObject failed (%d)\n", GetLastError());
  73.          }
  74.          else
  75.          {
  76.             printf("SetWaitableTimer failed with error %d\n", GetLastError());
  77.          }

  78.       }
  79.       __finally
  80.       {
  81.          CloseHandle( hTimer );
  82.       }
  83.    }
  84.    else
  85.    {
  86.       printf("CreateWaitableTimer failed with error %d\n", GetLastError());
  87.    }

  88.     return 0;
  89. }
发现定时器无法执行,因为cpu不是很高,确定不是死循环,检查了一下WCT,也没有发现死锁。
问了一下QQ好友,告诉因为使用WaitForSingleObject程序没有进入alertable state ,定时器无法调用。
看了一下msdn,
When a user-mode APC is queued, the thread to which it is queued is not directed to call the APC function unless it is in an alertable state. A thread enters an alertable state when it calls the SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx, WaitForMultipleObjectsEx, or WaitForSingleObjectEx function. If the wait is satisfied before the APC is queued, the thread is no longer in an alertable wait state so the APC function will not be executed. However, the APC is still queued, so the APC function will be executed when the thread calls another alertable wait function.
线程必须是被调用SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx, WaitForMultipleObjectsEx和 WaitForSingleObjectEx调用而进入等待状态。如果线程不在上面的函数中等待,系统不会把定时器的APC加入队列。


阅读(3566) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~