我编写了一个多线程程序,它会进行一些思考并一路打印出一些诊断信息。我注意到,如果我在程序运行时摇动鼠标,那么程序运行得更快。现在我可以在这里详细介绍我到底是如何打印的......但我现在会暂停,因为我注意到在许多其他程序中,如果鼠标抖动,事情会发生得更快,我想知道是否有这是许多人犯过的一个经典错误,其中消息循环因不移动的鼠标而减慢了速度。
编辑:我的“打印”方法如下......我有一个丰富的编辑控制窗口来显示文本。当我想要打印某些内容时,我将新文本附加到窗口内的现有文本上,然后使用 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 个问题:
WM_PAINT
的文档说:WM_PAINT 消息是由系统生成的,不应由应用程序发送。
不幸的是,我不知道任何消息解决方法,但我认为 SetWindowText() 将负责重新绘制窗口,因此此调用可能毫无用处。SendMessage() 是一个阻塞调用,直到应用程序处理完消息后才会返回。由于绘画可能需要一段时间才能处理,因此您的程序可能会卡在关键部分,特别是在考虑我的第三点时。 PostMessage() 在这里会好得多,因为您没有理由需要“立即”重新绘制窗口。
您在 MsgWaitForMultipleObjects() 中使用
QS_ALLEVENTS
,但此掩码不包含QS_SENDMESSAGE
标志。因此您的 SendMessage() 调用可能会被忽略并且不会唤醒您的线程。您应该使用QS_ALLINPUT
。
您可以检查应用程序在无限超时和上述 3 项修改的情况下的行为吗?
关于c++ - 鼠标抖动/消息处理循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1599604/