我编写了一个多线程程序,该程序进行了一些思考,并在此过程中打印出了一些诊断信息。我注意到,如果在程序运行时摇动鼠标,则程序运行速度会更快。现在我可以在这里详细介绍我的打印方式...但是我暂时不做介绍,因为我已经注意到,在许多其他程序中,如果摇动鼠标,事情会更快发生,我想知道是否有这是许多人犯下的一些经典错误,其中消息循环由于不动的鼠标而以某种方式减慢了速度。

编辑:我的“打印”方法如下...我有一个丰富的编辑控件窗口来显示文本。当我要打印某些内容时,我会将新文本附加到窗口中现有的文本上,然后使用SendMessage(,WM_PAINT,0,0)重新绘制窗口。

实际上,它有点复杂,我有多个丰富的编辑控制窗口,每个线程一个(我的4核PC上有4个线程)。我的“my_printf()”的大致轮廓如下:

void _cdecl my_printf(char *the_text_to_add)
{
    EnterCriticalSection(&my_printf_critsec);
    GetWindowText(...); // get the existing text
    SetWindowText(...); // append the_text_to_add
    SendMessage(...WM_PAINT...);
    LeaveCriticalSection(&my_printf_critsec);
}

我应该指出,多年来我一直在非多线程程序中使用这种打印方法,甚至没有注意到与鼠标跳动的任何交互。

编辑:好的,这是我的整个messageloop,它在子线程执行其工作时在根线程上运行。子线程调用my_printf()报告其进度。
for(;;)
{
    DWORD   dwWake;
    MSG msg;

    dwWake = MsgWaitForMultipleObjects(
                            current_size_of_handle_list,
                            hThrd,
                            FALSE,
                            INFINITE,
                            QS_ALLEVENTS);

    if (dwWake >= WAIT_OBJECT_0 && dwWake < (WAIT_OBJECT_0 + current_size_of_handle_list))
    {
        int index;
        index = dwWake - WAIT_OBJECT_0;
        int j;
        for (j = index+1;j < current_size_of_handle_list;j++)
        {
            hThrd[j-1] = hThrd[j];
        }
        current_size_of_handle_list--;
        if (current_size_of_handle_list == 0)
        {
            break;
        }

    }
    else if (dwWake == (WAIT_OBJECT_0 + current_size_of_handle_list))
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    else if (dwWake == WAIT_TIMEOUT)
    {
        printmessage("TIMEOUT!");
    }
    else
    {
        printmessage("Goof!");
    }
}

编辑:解决了!
这可能是一个丑陋的解决方案-但我只是将超时从无限更改为20ms,然后在if(dwWake == WAIT_TIMEOUT)部分中,我换了printmessage(“TIMEOUT!”);为了:
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

我还没有结束这个问题,因为我仍然想知道为什么原始代码本身不能全部工作。

最佳答案

我在这里可以看到3个问题:

  • WM_PAINT文档说:The WM_PAINT message is generated by the system and should not be sent by an application.不幸的是,我不知道任何解决方法,但我认为SetWindowText()将负责重新绘制窗口,因此此调用可能没有用。
  • SendMessage()是一个阻塞调用,只有在应用程序处理完消息后才会返回。由于绘画可能需要一段时间才能处理,因此您的程序可能会卡在关键部分,尤其是考虑到我的第三点时。 PostMessage()在这里会更好,因为您没有理由需要“立即”重新绘制窗口。
  • 您正在MsgWaitForMultipleObjects()中使用QS_ALLEVENTS,但是此掩码不包括QS_SENDMESSAGE标志。因此,您的SendMessage()调用可能会被忽略,并且不会唤醒您的线程。您应该使用QS_ALLINPUT

  • 您可以通过INFINITE超时和上述3种修改来检查应用程序的行为吗?

    关于c++ - 鼠标抖动/消息处理循环,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1599604/

    10-11 22:47
    查看更多