我在实际的生产代码中使用了以下代码的版本。它在将来的某个时间设置一个等待计时器,然后有一个工作线程等待它触发:
//Create timer
hWTimer = ::CreateWaitableTimer(NULL, FALSE, NULL);
//Number of minutes to wait
int nMinutesToWait = 5;
//Predict when it should fire
COleDateTime dtWhen = COleDateTime::GetCurrentTime() + COleDateTimeSpan(0, 0, nMinutesToWait, 0);
//Set timer
SetWaitableTimerSecondsFromNow(hWTimer, nMinutesToWait * 60);
//Waiting part
if(::WaitForSingleObject(hWTimer, INFINITE) == WAIT_OBJECT_0)
{
//Timer has fired, compare when
_TRACE(L"Time scheduled for: %s, time fired: %s",
dtWhen.Format(),
COleDateTime::GetCurrentTime().Format());
}
BOOL SetWaitableTimerSecondsFromNow(HANDLE hWTimer, double fSecs2Wait)
{
//INFO: I'm setting the timer to a relative time to ensure that it
// doesn't fire in case the system clock is adjusted.
LARGE_INTEGER li;
li.QuadPart = -10000000LL * (LONGLONG)fSecs2Wait; //Convert to 100 nanosecond intervals (MUST BE NEGATIVE)
if(li.QuadPart >= 0)
return FALSE;
return ::SetWaitableTimer(hWTimer, &li, 0, NULL, NULL, FALSE);
}
效果很好,在大多数情况下,计时器需要点火的时间和实际点火的时间是100%匹配。但是极少数情况下,计时器会提前10-15秒发射,仅需5分钟。似乎这个问题主要发生在Windows XP上。
有谁知道这里发生了什么以及如何减轻它?