【发布时间】:2014-06-18 09:05:02
【问题描述】:
我必须调试一些不是我的代码。 此代码使用 winapi Timer 接口实现了一个计时器 API。 我不太习惯这个 Winapi 功能,所以我可以使用你的帮助:)
据我了解,这段代码是这样完成的:
=> 初始化()
timerQueue = CreateTimerQueue();
=> CreateTimer()
CreateTimerQueueTimer(timerHandle, timerQueue, timerCallback, ..., WT_EXECUTEDEFAULT);
=> timerCallback()
DeleteTimerQueueTimer(timerQueue , timerHandle, NULL));
calback() //Launch user-defined callback
=> CleanUp() // 最后调用
DeleteTimerQueueEx(timerQueue , INVALID_HANDLE_VALUE);
当我们测试它时,用户定义的回调会在所需的时间后成功执行。但是在那之后 timerCallback 线程保持挂起并且永远不会返回,从而阻止所有进程返回。使用 VS 调试器,我可以在线程上看到那些线程(名为 TppWorkerThread@4)...
也许我们错过了一些使回调正确返回的东西,或者我们造成了某种死锁......但是我无法弄清楚......
如果我忘记了一些相关信息,请告诉我。
感谢您的帮助。
编辑:
更多信息:
- 阻塞线程在进程结束时处于此状态:
* 类别:工作线程
* 名称:_TppWorkerThread@4
* 位置:_ZwWaitForWorkViaWorkerFactory@8
* 优先级:正常
编辑2: 有更多时间来处理这种奇怪的行为,我现在可以在独立代码中重现它。
#include <windows.h>
#include <stdio.h>
HANDLE gDoneEvent;
HANDLE hTimer[5];
HANDLE hTimerQueue = NULL;
HANDLE g_threadHandle;
void PeriodicCallback(void)
{
printf("Periodic routine called.\n");
}
void SingleCallback(void)
{
printf("Single routine called.\n");
if (!DeleteTimerQueueTimer(hTimerQueue, hTimer[2], NULL))
printf("DeleteTimerQueueTimer() fail. Return value is %d.\n", GetLastError());
}
void CALLBACK CommonCallback(PVOID lpParam, BOOLEAN TimerOrWaitFired)
{
printf("Common routine called. Parameter is %d.\n", *(int *)lpParam);
((void (*)(void))lpParam)();
}
void MainTest(void)
{
// 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;
}
if(0 == SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL))
{
printf("SetThreadPriority failed (%d)\n", GetLastError());
return -2;
}
// Create the timer queue.
hTimerQueue = CreateTimerQueue();
if (NULL == hTimerQueue)
{
printf("CreateTimerQueue failed (%d)\n", GetLastError());
return -3;
}
/*
if (!CreateTimerQueueTimer( &hTimer[2], hTimerQueue,
(WAITORTIMERCALLBACK)CommonCallback, &SingleCallback, 1000, 0, WT_EXECUTEDEFAULT))
{
printf("CreateTimerQueueTimer failed (%d)\n", GetLastError());
return -4;
}
*/
if (!CreateTimerQueueTimer( &hTimer[4], hTimerQueue,
(WAITORTIMERCALLBACK)CommonCallback, &PeriodicCallback, 10, 500, WT_EXECUTEDEFAULT))
{
printf("CreateTimerQueueTimer failed (%d)\n", GetLastError());
return -5;
}
// TODO: Do other useful work here
printf("Call timer routine in 10 seconds...\n");
Sleep(4000);
CloseHandle(gDoneEvent);
if (!DeleteTimerQueueTimer(hTimerQueue, hTimer[4], INVALID_HANDLE_VALUE))
printf("DeleteTimerQueueTimer failed (%d)\n", GetLastError());
// Delete all timers in the timer queue.
if (!DeleteTimerQueueEx(hTimerQueue, INVALID_HANDLE_VALUE))
printf("DeleteTimerQueue failed (%d)\n", GetLastError());
Sleep(1000);
ExitThread(0);
}
int main(int argc, char **argv[])
{
if(g_threadHandle == CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MainTest, NULL, 0, NULL))
printf("Creation fail");
ExitThread(0);
}
我正在 VisualStudio 2010 Professional 上编译此代码。
在调用 DeleteTimerQueueTimer() 之后,似乎某些线程在线程池中仍处于待处理状态,从而阻止了我的进程关闭。我还是想不通...
【问题讨论】:
-
粘贴代码本身以进行推理会很有帮助。
-
DeleteTimerQueueEx 返回什么,如果为零,GetLastError 建议什么?
-
它返回 1。我认为这意味着成功,对吧?
-
我看不到您的所有代码,但看起来问题出在
CreateTimerQueueTimer的第一个参数上。您正在传递timerHandle,但您应该将 reference 传递给timerHandle。 IE。&timerHandle。这将解释继续调用计时器回调,因为您对DeleteTimerQueueTimer的调用传递了一个虚假的计时器句柄值。 -
正如其他人所说,请显示代码。展示一个完整的、简短的程序来说明问题。如果你这样做,你会得到一个明确的答案。如果你不这样做,你会得到猜测。