【发布时间】:2019-02-21 05:50:32
【问题描述】:
我正在创建一个手动等待计时器,如下所示
m_hTimer = CreateWaitableTimer(NULL, true, NULL);
并在函数中使用它
HRESULT ClassA::InduceSleep(UINT32 uiMiliSeconds)
{
if (m_hTimer)
{
LARGE_INTEGER liDueTime;
liDueTime.QuadPart = (uiMiliSeconds) * (-10000) * (1LL);
if (!SetWaitableTimer(m_hTimer, &liDueTime, 0, NULL, NULL, 0))
{
Log("SetWaitableTimer failed GLE[%d]", GetLastError());
goto exit;
}
// Wait for the timer.
if (WaitForSingleObject(m_hTimer, INFINITE) != WAIT_OBJECT_0)
{
Log("WaitForSingleObject failed GLE[%d]", GetLastError());
}
return S_OK;
}
exit:
Sleep(uiMiliSeconds);
return S_OK;
}
我观察到,在延迟 10 秒(或 5 秒)调用 InduceSleep() 时,waitforsingleobject 会立即返回 WAIT_OBJECT_0 而没有任何延迟,因此会立即发出计时器信号。文档中提到 setwaitable 计时器停止并重新激活计时器,因此它不应处于信号状态,并且应仅在给定时间后发出信号。我在这里错过了什么?
【问题讨论】:
-
出于好奇(但可能跑题了):为什么要
(-10000) * (1LL)?为什么不-10000LL?你调用函数时uiMilliSeconds的值是多少? -
顺便说一句。关于
(-10000) * (1LL)的问题还不错。 ;-)LL生成一个long long常量,它的字节数比UINT32多。这反转了类型提升并导致了long long乘法 (uiMiliseconds * -10000LL),即将uiMiliSeconds转换为long long并解决了您的问题。 -
我们需要
liDueTime.QuadPart = (LONGLONG)uiMiliSeconds * -10000LL代码 - 首先必须将uiMiliSeconds扩展为 64 位(它将是零扩展,因为uiMiliSeconds是无符号的,这没关系)然后在-10000LL上进行 mult(0xFFFFFFFFFFFFD8F0)。在您的代码中,您在FFFFD8F0h(-10000) 上 mult UINT32 并得到非常小的 正 值 - 绝对时间接近 1600 年