【问题标题】:How advisable is not having a message loop in WinMain?在 WinMain 中没有消息循环有多可取?
【发布时间】:2009-06-02 05:45:25
【问题描述】:

这可能是有史以来最简单的 win32 程序 ..

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR cmdLine, int show)
{
    MessageBox(0, "Hello world..", "Salutations!", MB_OK);
    return 0;
}

.. 它不会对通常的 GetMessage() 调用进行任何调用。我的问题是:如果我的程序不处理任何窗口消息,操作系统可以处理吗?即,它会导致内存泄漏吗?或者其他一些除非我运行 16K 次才会出现的资源?

从更广泛的意义上说,Win32 对处理其消息的应用程序究竟有多“依赖”?我希望当编译器将可执行文件作为 Windows 程序链接时,运行时能够清理任何类型的消息队列,无论它是否清空。

【问题讨论】:

  • 澄清一下——MessageBox() 仅用于说明我认为只是程序执行某事的简单方式。很抱歉在这种情况下对“窗口消息”的含义感到困惑。
  • 更改示例。就目前而言,你在这个程序中有一个消息循环,这不是你要问的。
  • @jmucchiello:我觉得他问题的意图还是很明确的,“错误”是一个很好的学习例子。

标签: winapi


【解决方案1】:

只是技术性问题,但您确实有一个窗口,并且确实有一个消息循环,只是不在您的代码中。

MessageBox() 的调用会创建一个窗口(属于#32770 类)并运行本地消息循环,在消息循环退出之前不会返回到您的代码,大概是在发送WM_NCDESTROY 时。我认为这与响应DialogBox() 运行的消息循环相同。

但是你可以用其他任何真正不会创建消息循环的东西来代替你对MessageBox() 的调用,你仍然会没事的。 Windows 不关心您是否有消息循环,尽管如果没有它,某些功能(主要是与 UI 相关的)很难或无法使用。事实上,你根本不需要链接到 user32,一些没有用户界面的应用也不需要。

现在,如果您创建一个窗口并且不以某些方式为其处理消息,Windows XP 及更高版本将用一个具有白色客户区和任务的“幽灵”窗口替换您的窗口Manager 会告诉用户应用程序没有响应。

虽然一开始看起来如此,但消息循环并不是魔术,也不是 Windows 样板文件中严格要求的部分。但是,它在大多数 Windows 应用程序中作为一个根深蒂固的标准,因为它是处理窗口消息分派的最佳方式。大多数 Windows 应用程序的“事件驱动”性质有时让我们忘记了 Windows 应用程序最初设计为单线程的,在这个模型中,它是在单线程中运行的代码,而不是操作系统中一些看不见的力量,这必须在我们的代码中进行每个函数调用。多线程的添加在一定程度上改变了这一点,但基本模型仍然保持不变。

编辑

关于消息队列的说明:

正如在别处提到的,消息队列仅在该线程创建窗口时创建(并且基于每个线程)。您的示例程序在创建消息框时,确实 创建了一个消息队列。但是当您的应用程序退出时,此队列不必为空。这个队列只是一个内存结构。它是一块内存,可以保存一定数量的消息对象(指定目标 hWnd、消息 id、wParam、lParam、消息发布时的系统时间、消息发布时的鼠标位置,以及一些允许派生键盘和消息发布时的鼠标按钮状态),以及指向队列头部和尾部的指针(我假设它是一个循环队列)。当应用程序退出时,这块内存和属于该进程的所有内存一样,会被立即释放。

当然,您的流程之外还有其他必须清理的事情。操作系统必须保留所有现有窗口的表格,例如,连同创建它们的线程和进程。当然,这些也都是自动清理的。

【讨论】:

  • 在所谓的“多线程 COM 单元”模型中,由于 COM 使用消息循环来编组这些对象之间的调用,所以在使用 COM 对象时不需要消息循环吗?
【解决方案2】:

由于您没有窗口,因此您不需要消息循环。在 Win32 中,消息被发送到窗口,而不是应用程序。

【讨论】:

  • 很抱歉,这是 100% 错误的。上面的程序确实有一个窗口,它确实有一个消息循环。
  • 我想我是在想这个问题,想象 Windows 会为每个进程创建一个消息队列,并且某些事情(尤其是初始化/清理)可能是“Windows 程序”所需要的' 可能会以这种方式运行。
  • 确定消息框创建了一个窗口,因此创建了一个循环,但这就是他要问的吗??
  • 根据需要为每个抽取消息和/或创建窗口的线程创建消息队列。通常这意味着每个进程有一个消息队列(但并非总是如此)
  • @1800 信息:当然它会显示一个对话框,但该对话框位于 Win32 API DLL 之一(如果我没记错的话,user32.dll)。因此消息循环也存在于那里......
【解决方案3】:

您确实有一个消息循环 - MessageBox 是一个模式对话框,因此其中包含一个消息循环。

【讨论】:

  • 嗯,好的,但是消息框只是作为一个简单的操作来说明程序实际上做了什么。
【解决方案4】:

您不必创建窗口。但是,还是有一些消息,比如

  • WM_TIMER
  • WM_TIMECHANGE
  • WM_CLIPBOARDUPDATE
  • WM_COPYDATA
  • WM_POWER

您可能需要。所以,一个 ghost 窗口挂在周围也不错。

【讨论】:

  • 幽灵窗口?你能详细说明一下吗?这听起来可能有用!
  • 幽灵窗口实际上与您所说的不同(请参阅我的帖子)。您指的是隐藏或不可见的窗口,它被称为仅消息窗口,有时也称为消息泵或消息接收器。
  • 是的,你是对的。我的意思是一个充当消息泵的窗口,一个用户看不到也无法交互的窗口。
【解决方案5】:

如果您没有窗口,那很好,但如果您有,那么您需要确保为它发送消息。否则系统可能会挂起等待您响应的广播消息。这对于像 COM 这样为消息处理创建隐藏窗口的东西很重要。如果您的主线程不发送消息(例如,通过调用 WaitForSingleObject),那么对您的 COM 对象的调用将不会被处理,并且任何发送广播的程序都会出现挂起。

【讨论】:

    【解决方案6】:

    我在某处读到(但找不到参考资料)是 Windows 将按需创建消息队列。如果您从不调用查找消息队列的函数,则永远不会创建消息队列。这发生在每个线程的基础上。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多