可能是多线程程序写多了,单线程程序居然不会用了。
最近做一个ETL工具,有个功能就是每个5分钟检查一下数据库的状态,因为是console程序,无法使用WM_TIMER。
我经常使用CreateTimerQueueTimer,这次决定使用SetWaitableTimer单线程的。
看了一下msdn,简单修改了一下
// Waitable.cpp : 定义控制台应用程序的入口点。
//
-
#include "stdafx.h"
-
#include <windows.h>
-
#include <stdio.h>
-
#include <tchar.h>
-
-
#define _SECOND 10000000
-
-
typedef struct _MYDATA {
-
TCHAR *szText;
-
DWORD dwValue;
-
} MYDATA;
-
HANDLE gDoneEvent;
-
-
VOID CALLBACK TimerAPCProc(
-
LPVOID lpArg, // Data value
-
DWORD dwTimerLowValue, // Timer low value
-
DWORD dwTimerHighValue ) // Timer high value
-
-
{
-
// Formal parameters not used in this example.
-
UNREFERENCED_PARAMETER(dwTimerLowValue);
-
UNREFERENCED_PARAMETER(dwTimerHighValue);
-
-
MYDATA *pMyData = (MYDATA *)lpArg;
-
-
_tprintf( TEXT("Message: %s\nValue: %d\n\n"), pMyData->szText,
-
pMyData->dwValue );
-
MessageBeep(0);
-
-
}
-
-
int _tmain(int argc, _TCHAR* argv[])
-
{
-
HANDLE hTimer;
-
BOOL bSuccess;
-
__int64 qwDueTime;
-
LARGE_INTEGER liDueTime;
-
MYDATA MyData;
-
-
MyData.szText = TEXT("This is my data");
-
MyData.dwValue = 100;
-
-
// 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;
-
}
-
-
-
hTimer = CreateWaitableTimer(
-
NULL, // Default security attributes
-
FALSE, // Create auto-reset timer
-
TEXT("MyTimer")); // Name of waitable timer
-
if (hTimer != NULL)
-
{
-
__try
-
{
-
// Create an integer that will be used to signal the timer
-
// 5 seconds from now.
-
qwDueTime = -5 * _SECOND;
-
-
// Copy the relative time into a LARGE_INTEGER.
-
liDueTime.LowPart = (DWORD) ( qwDueTime & 0xFFFFFFFF );
-
liDueTime.HighPart = (LONG) ( qwDueTime >> 32 );
-
-
bSuccess = SetWaitableTimer(
-
hTimer, // Handle to the timer object
-
&liDueTime, // When timer will become signaled
-
2000, // Periodic timer interval of 2 seconds
-
TimerAPCProc, // Completion routine
-
&MyData, // Argument to the completion routine
-
FALSE ); // Do not restore a suspended system
-
-
if ( bSuccess )
-
{
-
/*
-
for ( ; MyData.dwValue < 1000; MyData.dwValue += 100 )
-
{
-
SleepEx(
-
INFINITE, // Wait forever
-
TRUE ); // Put thread in an alertable state
-
}
-
*/
-
if (WaitForSingleObject(gDoneEvent, INFINITE) != WAIT_OBJECT_0)
-
printf("WaitForSingleObject failed (%d)\n", GetLastError());
-
}
-
else
-
{
-
printf("SetWaitableTimer failed with error %d\n", GetLastError());
-
}
-
-
}
-
__finally
-
{
-
CloseHandle( hTimer );
-
}
-
}
-
else
-
{
-
printf("CreateWaitableTimer failed with error %d\n", GetLastError());
-
}
-
-
return 0;
-
}
发现定时器无法执行,因为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加入队列。
阅读(3614) | 评论(0) | 转发(0) |