寻找一种快速安全地杀死线程的好方法

时间:2014-02-13 20:55:01

标签: c++ multithreading winapi

这是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专业知识的人都知道如何快速安全地杀死线程?

0 个答案:

没有答案