【问题标题】:Timing of calling .NET WinForms Event Handlers调用 .NET WinForms 事件处理程序的时机
【发布时间】:2013-07-10 02:33:02
【问题描述】:

用户是否可以在 WinForms 中执行某些操作(例如单击按钮)并在 UI 线程上执行一些任意代码在 UI 上执行该操作的事件处理程序之前线? (编辑:我不想自己这样做。我想知道它是否真的会发生。如,我需要担心吗?)

我对如何在 .NET 中为 GUI 事件调用事件处理程序有点模糊,并且我遇到了这种实现细节很重要的情况。

**编辑***
我不关心如何连接事件处理程序,甚至不关心如何以编程方式引发事件。我关心的是我已经连接的事件处理程序如何作为 UI 操作的结果被调用的幕后细节。更具体地说,我很好奇事件处理程序的调用(或导致它的事件序列)是否简单地添加到表单的消息循环中。 “直观地”显示 UI 线程可能更容易......

时间 --------->
检测到物理点击......(其他东西可以在这里点击 UI 线程)............点击事件处理程序调用

【问题讨论】:

  • 你想做什么?如果这是您自己的代码,只需将其放在其他逻辑之前的事件处理程序中...
  • 有几种可能的技术,并非所有技术都适用于每种情况。你的具体是非常重要的。
  • 您可能想阅读Control.WndProc()windows procedures in general。这些是 Win32 API(Windows 窗体所基于)中所有 UI 事件处理的基础。
  • 单击按钮会导致将消息发布到 UI 消息队列。该消息将由消息循环处理,但如果你有一个计时器,它可能会在那个精确的时刻发布另一条消息,就在“你的”之前,或者一个外部消息,就像其他一些应用程序抓住焦点一样发生,但这种情况很少见。逻辑通常不会突然被调用。
  • 非常正确,逻辑不会突然被调用,尽管有时我在工作中看到的东西......实际上,我的问题受到应用程序中其他线程正在调用的事实的启发东西到 UI 线程

标签: .net winforms


【解决方案1】:

有两种方法可以做到这一点。

Windows 窗体中的大多数控件都提供了一种用于引发事件的方法。如果将控件子类化,则可以在引发事件之前将自定义代码放入方法中。

例如,您可以继承Button,并覆盖OnClick

override void OnClick(EventArgs e)
{
    // Your code here...
    base.OnClick(e); // This will raise the Click event
}

另一个选项是订阅事件首先,然后将您的代码放入事件处理程序中。默认情况下,事件处理程序将按顺序调用每个订阅的委托。


我关心的是我已经连接的事件处理程序如何作为 UI 操作的结果被调用的底层细节。更具体地说,我很好奇事件处理程序的调用(或导致它的事件序列)是否只是简单地添加到表单的消息循环中。

当用户点击一个按钮时,鼠标事件被发送到应用程序的消息循环中。 Button 在 WndProc 覆盖中处理此消息(通过处理定义为 WM_REFLECT + WM_COMMAND 的消息)。

如果您的问题是“其他代码是否可以在用户单击和事件处理程序之间运行”,那么可以 - 代码可以在用户单击时运行,并且该代码将继续运行,直到消息泵可以处理消息。

【讨论】:

  • 甚至不接近我的要求。请参阅更新的问题。不过,谢谢。
  • @aaronburro 我添加了一个我〜相信〜回答你的问题的编辑 - 目前尚不完全清楚你在这里追求什么......
  • 您的编辑很有用,几乎回答了我的问题...“其他代码可以在...之间运行吗”应该更改为“其他代码可以在 UI 线程上运行之间……”
  • @aaronburro 答案是“是的,点击窗口消息被放入消息队列中以得到处理,所有排队但当时尚未处理的消息发生的点击将在点击处理之前发生。”
【解决方案2】:

您最好的选择可能是将您的按钮子类化,然后将您的代码添加到覆盖的OnClick 方法中(在调用基础OnClick 之前)。该代码将在任何附加的事件处理程序(点击)之前执行。

【讨论】:

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