c++ - 如何使用 WaitForMultipleObjects 来平衡竞争工作?

标签 c++ windows multithreading winapi visual-c++

我正在使用 WaitForMultipleObjects在 IPC 情况下,我有一个进程将数据写入两个内存映射文件中的一个或两个,另一个进程在数据更新时获取该数据。当任一 MMF 中的数据发生更改时,我使用命名事件对象通知第二个进程。还有一个终止“观察者”线程的事件。

所以代码的简化示例是这样的(编辑 - 请注意事件对象已创建为自动重置事件)

unsigned int CMyClass::ThreadFunc()
{
    // background thread
    HANDLE hEvent[3];

    // open events for updates 0 and 1 and kill signal
    hEvent[0] = ::OpenEvent(SYNCHRONIZE, FALSE, _T("KillEvent"));
    hEvent[1] = ::OpenEvent(SYNCHRONIZE, FALSE, _T("UpdateEvent0"));
    hEvent[2] = ::OpenEvent(SYNCHRONIZE, FALSE, _T("UpdateEvent1"));

    // main loop
    while (true)
    {
        // wait for any event and break on kill signal
        DWORD dwRet = WaitForMultipleObjects(3, hEvent, FALSE, INFINITE);
        if (dwRet == WAIT_OBJECT_0) break;

        // which update event did we get?
        if (dwRet == WAIT_OBJECT_0 + 1) 
        {
            // perform update from channel 0
        }
        else if (dwRet == WAIT_OBJECT_0 + 2)  
        {
            // perform update from channel 1
        }
    }

    // release handles 
    for (int i = 0; i < 3; ++i)
        CloseHandle(hEvent[i]);

    // exit thread
    return 0;
}

在最常见的用例中,只有一个 MMF 被更新,因此这段代码工作正常。但是,当两个 MMF 都被更新时,我得到了两个事件信号,我通过日志记录和调试注意到第一个事件的处理频率大约是第二个事件的两倍 - 即使进程执行更新只是在相邻代码行中对每个更新调用 SetEvent。这使得一个更新比另一个慢,因此出现了来自用户的错误报告。

仔细观察 MSDN , 它表明了为什么会发生这种情况

If multiple objects become signaled, the function returns the index of the first handle in the array whose object was signaled.

因此,如果上面代码中的处理设法在 另一个 SetEvent 被第一个事件调用之前完成执行,那么第二个事件似乎只是打破了等待。

因此,为了暂时解决这个问题,我只是单方面执行两个更新,而不考虑设置了哪个事件。

        // wait for any event
        DWORD dwRet = WaitForMultipleObjects(3, hEvent, FALSE, INFINITE);
        if (dwRet == WAIT_OBJECT_0) break;

        // perform update from channel 0

        // perform update from channel 1

这显然不理想,而且非常浪费,因为正如我上面所说,对于最常见的用例,只有 一个 MMF 正在更新。

处理这种情况的最佳方法是什么?我考虑过使用两个线程——一个线程用于每个 MMF 和相应的事件——但是“更新”代码对两者都是通用的,并且会涉及添加很多目前不需要的同步。

我还有其他选择吗?

最佳答案

处理一个事件后,您可以在下一次调用中重新排列传递给 WaitForMultipleObjects 的句柄数组。因此,完成事件 1 会使事件 2 成为下一次的优先事件。反之亦然。

关于c++ - 如何使用 WaitForMultipleObjects 来平衡竞争工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16830227/

相关文章:

c++ - 重载函数隐藏在派生类中

c++ - cmake 不会编译为 C++ 11 标准

c++ - shared_ptr C++ 双重删除错误

javascript - 读/写 Windows 图像标签(关键字)

windows - 文件存在和不存在的奇怪情况

c++ - 关于c++中的结构填充

windows - 实现 DebugExtensionProvideValue 会破坏 WinDbg 内部状态?

.net - 与从非 GUI 线程显示 MessageBox 相关的问题

Java合并排序算法与wait()/notify()同步

c# - 等待来自不同类(class)的任务