这是Timing inconsistency with killing thread using event
的后续问题简而言之,我有一个主线程试图通过发送信号来杀死工作线程。但是工作线程可能很忙,直到很久之后才能获得终止信号。这是代码:
// Main thread code
void deactivate()
{
while (isWorkerThreadRunning)
{
// Problem: sometimes it spends a long time in this loop
logDebug("deactivate: killing worker thread");
SetEvent(killWorker);
Sleep(20);
}
}
// Worker thread code
DWORD WINAPI WorkerThreadProc(LPVOID arglist)
{
isWorkerThreadRunning = true;
logDebug("Worker thread started");
for (bool done = false; done != true; )
{
HANDLE handles[3] = { killWorker, action1, action2 };
DWORD rc = WaitForMultipleObjects(3, handles, FALSE, INFINITE);
switch (rc)
{
case WAIT_OBJECT_0 + 0: done = true; break;
case WAIT_OBJECT_0 + 1: doAction1(); break;
case WAIT_OBJECT_0 + 2: doAction2(); break;
default: logWarn("Unhandled wait signal");
}
}
isWorkerThreadRunning = false;
logDebug("Worker thread killed");
return 0;
}
void doAction1()
{
// some potentially time consuming processing
callbackToManagedCode(arg1); // this can take a long time too
// some more potentially time consuming processing
}
问题是doAction1()可能需要很长时间。我想知道doAction1()在发送终止信号之前完全退出之前是否有好办法退出。猴子扳手是从这个非托管代码到一些托管代码的回调。
我正在考虑将doAction1()修改为:
void doAction1()
{
bool done = false;
bool part1done = false;
bool part2done = false;
bool part3done = false;
while (!done)
{
DWORD rc = WaitForSingleObject(killWorker, 20);
switch (rc)
{
case WAIT_OBJECT_0:
done = true; break;
case WAIT_TIMEOUT:
if (!part1done)
{
doAction1Part1();
part1done = true;
}
else if (!part2done)
{
callbackToManagedCode(arg1);
part2done = true;
}
else if (!part3done)
{
doAction1Part3();
done = true;
}
break;
default:
logWarn("Unhandled wait signal"); break;
}
}
}
这样可以更快地捕获终止信号。如果我需要它更快,我可以应用相同的策略并以相同的方式分解doAction1Part1()和doAction1Part3()。但是,仍有3个问题:
1)这对callbackToManagedCode()没有帮助。如果由于某种原因该调用未返回,则应用程序将挂起。我尝试将try / catch块放在它周围,但如果回调进入Neverland,这似乎没什么帮助。
2)如果doAction1()消耗了kill信号,则它不会被工作线程中的主循环捕获。如果仅发出一次终止信号,这可能是一个问题。
3)如果doAction1Part1()和doAction1Part3()仍然需要很长时间,我需要使用与doAction1()相同的策略将其分解。但这很快就会变得混乱。
最后的手段是TerminateThread()。但是我不想去那里。
任何具有WINAPI专业知识的人都知道如何快速安全地杀死线程?