使用事件杀死线程的时间不一致

Posted

技术标签:

【中文标题】使用事件杀死线程的时间不一致【英文标题】:Timing inconsistency with killing thread using event 【发布时间】:2014-02-11 20:45:40 【问题描述】:

我有一个多线程 C++ Windows 应用程序。工作线程是一个等待事件处理的无限循环,其中之一是来自主线程的终止线程事件。问题是有时工作线程需要很长时间(想想几秒钟)才能接收到 kill 事件并终止。其他时候非常快(毫秒)。

// 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;

我相信,如果工作线程在 doAction1() 或 doAction2() 内忙碌时接收到 kill 事件,则在 doAction1() 或 doAction2() 完成并返回之前不会接收和处理 kill 事件。如果 doAction1() 或 doAction2() 需要很长时间才能返回,那么工作线程将需要很长时间才能退出。

但是,我在 doAction1() 和 doAction2() 中散布了日志点,但我在日志文件中看不到任何这些日志点。我看到的只有:

deactivate: killing worker thread
deactivate: killing worker thread
deactivate: killing worker thread
deactivate: killing worker thread
//....many more times
Worker thead killed

这意味着工作线程没有做任何工作,而是在 WaitForMultipleObjects() 调用中等待。

问题是为什么 WaitForMultipleObjects() 调用有时需要很长时间(有时非常快)才能向服务员发出事件信号??

将超时从 INFINITE 更改为某个合理的数字会解决此问题吗?

谢谢,

【问题讨论】:

没有什么明显的错误。如果您注释掉对doAction1()doAction2() 的调用,您还会看到延迟吗? 哦,您的活动会自动重置吗?如果是这样,请尝试手动重置。 唯一合理的解释是你所建议的 - 线程正在执行“doActionX”调用之一。 在设置事件终止线程之前,您可以尝试增加要终止线程的优先级。 @rcgldr 谢谢你的建议,我试试看。 【参考方案1】:

如果不是,您的 isWorkerThreadRunning 声明应该是 volatile 的。如果代码不是 volatile,编译器优化代码时可能会出现一些奇怪的行为。

volatile bool isWorkerThreadRunning;

我还建议在您的 doAction 函数中输入和退出消息。如果您在发送退出信号时仍在其中一个函数中,那将会更清楚。

【讨论】:

以上是关于使用事件杀死线程的时间不一致的主要内容,如果未能解决你的问题,请参考以下文章

使用 openmp 时运行的线程数不一致

使用 Armadillo 和 OpenBLAS 进行多线程处理时性能不一致

SharePoint 全天事件不一致

不一致的“跨线程操作无效”异常

JMeter:JDBC 删除不一致

为啥 bind() 在 Vue 模板事件处理程序中的工作方式如此不一致?