SetThreadpoolTimerEx返回FALSE却未触发回调的罕见问题求助
罕见问题:SetThreadpoolTimerEx未按预期调用回调函数
环境信息
- 操作系统:Windows 10 22H2(版本19045.5131)
- Visual Studio:2022(版本17.12.0)
- SDK与工具集:Windows SDK 10.0.19041.0,Platform Toolset v143
问题详情
根据SetThreadpoolTimerEx的官方文档说明:
若定时器先前状态为“已设置”且函数返回FALSE,则回调正在执行或即将启动。
但在实际场景中,该函数返回FALSE,回调却未被调用,导致程序因等待回调信号完成而挂起。
复现用C++代码
#include <iostream> #include <atomic> #include <chrono> #include <Windows.h> std::atomic<bool> callbackDone = false; VOID(NTAPI callback)( _Inout_ PTP_CALLBACK_INSTANCE Instance, _Inout_opt_ PVOID Context, _Inout_ PTP_TIMER Timer ) { printf("callback...\n"); callbackDone = true; } int main() { bool canFail = false; while (true) { callbackDone = false; auto timer = CreateThreadpoolTimer(callback, nullptr, nullptr); LARGE_INTEGER relativeTime = {}; relativeTime.QuadPart = 10000000 * -1; FILETIME relativeTimeFt = {}; relativeTimeFt.dwLowDateTime = relativeTime.LowPart; relativeTimeFt.dwHighDateTime = static_cast<DWORD>(relativeTime.HighPart); auto setRes1 = SetThreadpoolTimerEx(timer, &relativeTimeFt, 0, 0); Sleep(999); auto setRes2 = SetThreadpoolTimerEx(timer, nullptr, 0, 0); if (setRes2 == TRUE) { FILETIME now = {}; SetThreadpoolTimerEx(timer, &now, 0, 0); } else { if (!callbackDone) { WaitForThreadpoolTimerCallbacks(timer, FALSE); canFail = true; } } if (canFail) { printf("waiting for possibly failed timer\n"); } auto startWaitTime = std::chrono::high_resolution_clock::now(); auto waitMsgStep = std::chrono::seconds(10); auto nextMsgTime = waitMsgStep; while (!callbackDone) { SleepEx(10, TRUE); auto waitDuration = std::chrono::duration_cast<std::chrono::seconds>( std::chrono::high_resolution_clock::now() - startWaitTime ); if (waitDuration > nextMsgTime) { printf("waiting for callback to finish for %d seconds...\n", static_cast<DWORD>(nextMsgTime.count())); nextMsgTime += waitMsgStep; } } if (canFail) { canFail = false; printf("timer is ok\n"); } CloseThreadpoolTimer(timer); } }
可能的输出

核心问题
即便SetThreadpoolTimerEx返回FALSE(按文档说明回调应正在执行或即将启动),但在部分罕见场景下回调从未被调用,导致程序无限挂起在等待callbackDone变为true的循环中。
疑问
- SetThreadpoolTimerEx是否存在已知问题:返回FALSE但回调未被触发?
- 是否因误用线程池定时器API导致该行为?
- 如何修改代码确保回调总能被触发,或正确处理未触发的情况?
补充信息
来自Raymond Chen博客的说明:
最后一种情况很有意思:当你取消定时器或等待对象时,线程池会尝试撤回所有待处理的回调,但有时回调已执行到无法撤回的阶段(比如已在执行中),此时Set...Ex函数会返回FALSE,提示你操作尚未完成,需等待回调执行完毕。
但在实际场景中,SetThreadpoolTimerEx返回FALSE后,等待了10秒甚至更久,回调仍未触发。
内容的提问来源于stack exchange,提问作者user2440195
相关产品推荐
相关产品推荐

