c++ - 鼠标抖动/消息处理循环

标签 c++ multithreading windows-xp

我编写了一个多线程程序,它会进行一些思考并一路打印出一些诊断信息。我注意到,如果我在程序运行时摇动鼠标,那么程序运行得更快。现在我可以在这里详细介绍我到底是如何打印的......但我现在会暂停,因为我注意到在许多其他程序中,如果鼠标抖动,事情会发生得更快,我想知道是否有这是许多人犯过的一个经典错误,其中消息循环因不移动的鼠标而减慢了速度。

编辑:我的“打印”方法如下......我有一个丰富的编辑控制窗口来显示文本。当我想要打印某些内容时,我将新文本附加到窗口内的现有文本上,然后使用 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);
}

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

编辑:好的,这是我在根线程上运行的整个消息循环,而子线程则执行其工作。子线程调用 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 个问题:

  1. WM_PAINT 的文档说:WM_PAINT 消息是由系统生成的,不应由应用程序发送。 不幸的是,我不知道任何消息解决方法,但我认为 SetWindowText() 将负责重新绘制窗口,因此此调用可能毫无用处。

  2. SendMessage() 是一个阻塞调用,直到应用程序处理完消息后才会返回。由于绘画可能需要一段时间才能处理,因此您的程序可能会卡在关键部分,特别是在考虑我的第三点时。 PostMessage() 在这里会好得多,因为您没有理由需要“立即”重新绘制窗口。

  3. 您在 MsgWaitForMultipleObjects() 中使用 QS_ALLEVENTS,但此掩码不包含 QS_SENDMESSAGE 标志。因此您的 SendMessage() 调用可能会被忽略并且不会唤醒您的线程。您应该使用QS_ALLINPUT

您可以检查应用程序在无限超时和上述 3 项修改的情况下的行为吗?

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

相关文章:

c++ - 为什么这个 OpenCV 代码什么都不做?

c++ - 由于多线程(使用 boost 库)导致的 seg 错误

C++ 程序仅在安装 Visual Studio 后才能在 XP SP2 上运行

windows-services - 在Windows XP中启动和停止Windows服务的更简单方法

node.js - 在 Node js 中,libuv 是什么?它是否使用所有核心?

authentication - Okuma - 如何打开 Windows 开始菜单

c++ - CW2A(LPCWSTR)str) 和 CW2A(LPCWSTR)str, CP_UTF8) 有什么区别?

c++ - 将基指针转换为派生指针有任何危险吗?

c++ - 堆栈及其实现

java - 多线程排序算法