【问题标题】:C# Console App + Event HandlingC# 控制台应用程序 + 事件处理
【发布时间】:2010-10-20 09:00:40
【问题描述】:

大家好。我正在尝试了解如何在控制台应用程序中处理事件。我宁愿不使用静默 WinForms(尽管我知道这是一种方法)来做到这一点。我已经阅读了一个类似的问题及其回复。请参阅下面的回复文本 (link):

一个STA线程的基本要求 是它需要运行一条消息 泵。在 Windows 窗体中,您可以使用 应用程序运行。或者你可以写 手动消息泵,使用 user32!GetMessage 和 DispatchMessage。 但它可能更容易使用 WinForms 或 WPF 中的一个。

使用“user32 -> GetMessage”和“user32 -> DispatchMessage”的程序的基本结构是什么?

【问题讨论】:

标签: c# event-handling console-application


【解决方案1】:

请参阅 MSDN 中的“使用消息和消息队列”主题(在 Win32 和 COM 开发 > 用户界面 > Windows 用户体验 > Windows 管理 > Windows 用户界面 > 窗口化 > 消息和消息队列下;您可能需要采取查看同一部分中的其他文章和示例)。快速总结,省略错误处理并使用 C 语法而不是 C#,原因如下:

RegisterClass(...);
CreateWindow(...);
ShowWindow(...);  // probably not in your case
while (GetMessage(&msg, NULL, 0, 0)) {
  TranslateMessage(&msg);
  DispatchMessage(&msg);
}

从窗口设置样板中可以看出,这仍然依赖于“静默窗口”,尽管它是通过 Win32 API 而不是通过 WinForms 创建和发送消息的。所以你这样做并没有真正获得任何东西。因此,我觉得将这些东西翻译成 C# 并没有多大意义——如果您的问题的唯一解决方案是一个不可见的窗口,那么您不妨使用一个不可见的 Windows 窗体以及该平台附带的所有友好包装器。

但是,如果您实际上并没有像链接问题的海报那样使用 Windows 窗体控件,那么您可以很高兴地在控制台应用程序中使用 .NET 事件。对 STA 的限制和对消息泵的需求特定于从 WinForms 和 ActiveX 控件(如 WebBrowser)接收事件(或来自 Win32 HWND 的消息,尽管这不一定需要 STA)。

【讨论】:

    【解决方案2】:

    你想处理什么样的事件?设置消息泵将允许您处理 Windows API 消息。但由于这是一个控制台应用程序,我想不出任何感兴趣的 Windows API 消息。

    我们倾向于将“事件”视为与 Windows 消息相关联,因为 Windows 窗体应用程序中的控件使用 EventHandler 委托来响应用户输入,这些委托被调用以响应 Windows API 消息。但是,没有理由不能在控制台应用程序中使用委托。而且您不需要消息泵。您甚至可以使用 EventHandler 委托,尽管它看起来不合适,因为它不会响应 Windows API 消息。

    当然,还有其他类型的“事件”您可能会感兴趣。涉及控制台应用程序的最常见的事件场景是等待来自控制台的输入 (stdin)。如果有多个线程在使用,阻塞 WaitHandle 或其他同步对象也很常见。这两种情况都可以被认为是一种事件处理。

    如果您创建了一个隐藏的窗口(一个由来已久的做法),您仍然需要一条 Windows 消息来响应。所以问题是:你想要回应什么或回应谁?

    【讨论】:

    • 我能想到一个:WM_CLOSE。假设您将批处理作业实现为控制台。该批处理旨在使用 Windows 任务计划程序或类似工具进行计划。如果任务运行时间超过某个指定的持续时间,它具有停止任务的功能。我不知道 WTM 是否真的发送了 WM_CLOSE 来让进程有机会优雅地自行关闭,但至少看起来是合理的。
    • 不,如果命令行进程被中止,它们不会收到 WM_CLOSE。为了拦截和中止,实现一个控制台 ctrl 处理程序:msdn.microsoft.com/en-us/library/ms686016(VS.85).aspx 对于必须能够优雅地拆除的批处理,我会考虑部署为服务进程而不是批处理。
    • 像“KeyDown”“KeyRepeat”“KeyRepeat”“KeyRepeat”“KeyUp”这样的事件。
    【解决方案3】:

    我会使用 Application.Run 方法。我不认为它会自动创建隐藏窗口,它只是泵送消息,这是您满足 STA 要求所需要的。

    使用 PInvoke 编写您自己的消息泵没有任何优势,并且引用 System.Windows.Forms 也不是什么负担,因为它已经在您可能遇到的每台机器上。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-07
      • 1970-01-01
      • 2011-09-05
      • 1970-01-01
      • 1970-01-01
      • 2012-07-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多