Это простая ошибка:
uiMiliSeconds
имеет тип UINT32
, т. Е. Тип без знака.
Это делает
(uiMiliSeconds) * (-10000)
умножением без знака, т.е.-10000
преобразуется в unsigned
перед умножением.(Согласен, продвижение типов иногда является сложной темой.)
Я пробовал это в минимальном примере:
#include <iostream>
int main()
{
uint32_t uiMilliseconds = 10 * 1000;
std::cout << uiMilliseconds * -10000 << '\n';
std::cout << (int)uiMilliseconds * -10000 << '\n';
return 0;
}
Вывод:
4194967296
-100000000
Демонстрация в реальном времени на coliru
Итак, решение заключается в простом преобразовании uiMiliseconds
в целое число со знаком перед умножением (как я делал во втором выводелиния).
Остальная часть истории, вероятно, очевидна для ОП.Из MSDN о функция SetWaitableTimer :
lpDueTime
Время, по истечении которого состояние таймера должно быть установлено в виде сигнала, с интервалом в 100 наносекунд,Используйте формат, описанный структурой FILETIME.Положительные значения указывают абсолютное время.Обязательно используйте абсолютное время в формате UTC, поскольку система использует внутреннее время в формате UTC.Отрицательные значения указывают относительное время.
Таким образом, неправильное вычисленное время, похоже, дает значение, которое уже есть в прошлом.Это единственное разумное объяснение, почему SetWaitableTimer(m_hTimer, &liDueTime, 0, NULL, NULL, 0)
возвращается немедленно.(OP проверил наличие ошибок и не распознал их.)
Чтобы сделать его "пуленепробиваемым", я бы рекомендовал
uiMiliSeconds * -10000LL
, учитывая, что, например, VC использует 32 битадля int
(даже для x64).Таким образом, из-за продвижения типа любое значение UINT32
расширилось бы до соответствующего long long
без опасности переполнения.
RbMm пожаловался, что тип UINT32
для MiliSeconds
может быть нетакой удачный выбор, поскольку он охватывает только поддиапазон времени, который может быть установлен.В случае OP этого поддиапазона может быть достаточно.В противном случае можно указать тип UINT64
.