使用`PostQuitMessage`和处理所有消息之间有区别吗?

时间:2014-10-10 18:33:51

标签: c windows winapi

我想知道这两个片段之间是否存在差异:

一:

void main()
{
    // ...

    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    ExitProcess(0);
}

// ...

void quit()
{
    PostQuitMessage(0);
}

两个

bool quit = false;

void main()
{
    // ...

    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
        if(quit)
        {
            while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&_msg);
            }
            ExitProcess(0);
        }
    }

    // Shouldn't get here
    ExitProcess(1);
}

// ...

void quit()
{
    quit = true;
    PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0);
}

很抱歉,但我无法提出更短的代码段。

我的问题是,调用PostQuitMessage并使用GetMessage处理所有邮件是否等同于处理PeekMessage的所有邮件,直到它返回FALSE

According to RaymondWM_QUIT仅在消息队列为空时生成",所以看起来两种方法应该相同,但可能在那里"一个微妙的区别。

2 个答案:

答案 0 :(得分:6)

雷蒙德的博文说:

  

因为系统尝试不在"坏的情况下注入WM_QUIT消息   时间&#34 ;;相反,它等待着#34;安定下来"在生成之前   WM_QUIT消息,从而减少了程序的机会   可能正处于由a触发的多步骤过程中   发布的消息序列。

所以理论上没有,没有区别,因为系统在队列为空之前不会生成WM_QUIT。然而,雷蒙德并没有说它是保证消息在WM_QUIT生成后不会到达,只是系统尝试避免它。

因此,可以想象,在您退出主GetMessage循环后,另一个主题可能会向您发送消息,并且根据您的应用,这可能是您必须处理的内容。例如,如果您在内部发布带有内存分配的消息,接收线程应该是空闲的,那么在线程完全退出之前,您可能需要一个单独的PeekMessage循环来清理它们。

在实践中,没有人像你的第二个例子那样编写消息循环。

答案 1 :(得分:1)

我认为接受的答案没有解决真正的问题。
雷蒙德直接here回答了这个问题。

基本上:

  1. 您无法控制每个消息循环,因此您没有那个选项。

  2. 哦,顺便说一句,别忘了PostQuitMessage 在你自己的消息循环中
    请注意,even WTL neglects to do this!
    它依赖于CMessageLoop::Run的返回值传递给PostQuitMessage