.NET WinForms事件处理程序的调用时间

3
用户在WinForms中执行某些操作(例如点击按钮),并在UI线程上执行任意代码,然后在UI线程上执行该操作的事件处理程序之前,这是否可能发生?(编辑:我不想自己做这个。我想知道它是否真的会发生。也就是说,我需要担心吗?)
我对.NET GUI事件中的事件处理程序如何调用有点模糊,并且我遇到了一个重要的实现细节。
编辑: 我不关心如何连接事件处理程序或甚至如何以编程方式引发事件。我关心的是已经连接的事件处理程序作为UI操作结果如何被调用的底层细节。更具体地说,我想知道调用事件处理程序(或导致其发生的事件序列)是否只是添加到窗体的消息循环中。可能更容易“视觉化”UI线程...
时间 ---------> 检测到物理点击....(其他东西可以在此命中UI线程)..........调用单击事件处理程序

你想要做什么?如果这是你自己的代码,只需将其放在其他逻辑之前的事件处理程序中即可... - Reed Copsey
有几种可能的技术,但并不是每种技术都适用于每种情况。因此,非常重要的是你要具体明确。 - Hans Passant
你可能想要阅读 Control.WndProc()Windows 过程的一般知识。这些是 Win32 API(Windows Forms 基于此)中所有 UI 事件处理的基础。 - stakx - no longer contributing
1
点击按钮会导致消息被发布到UI消息队列。该消息将成为消息循环处理的下一个消息,但如果您有一个计时器,它可能会在那个特定时刻发布另一条消息,领先于“您”的消息,或者外部消息,例如其他应用程序抓取焦点也可能发生,但这种情况很少发生。逻辑通常不会无缘无故地被调用。 - 500 - Internal Server Error
非常正确,逻辑并不会无缘无故地被调用,尽管有时候在工作中我看到的东西......实际上,我的问题是受到其他应用程序线程将东西调用到UI线程的事实启发的。 - aaronburro
2个回答

4

有两种方法可以完成这个任务。

Windows Forms中的大多数控件都提供了用于触发事件的方法。如果您对控件进行子类化,您可以在触发事件之前在该方法中放置自定义代码。

例如,您可以对Button进行子类化,并重写OnClick方法:

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

另一种选择是先订阅事件,然后将您的代码放在事件处理程序中。默认情况下,事件处理程序将按顺序调用每个已订阅的委托。
当用户单击按钮时,鼠标事件会被发布到应用程序的消息循环中。按钮通过处理定义为“WM_REFLECT + WM_COMMAND”的消息的WndProc重写来处理此消息。
如果您的问题是“用户单击时是否可以运行其他代码”,那么是的-代码可以在用户单击时运行,并且该代码将继续运行,直到消息泵可以处理消息。

离我所问的还差得远呢。请查看更新后的问题。不过还是谢谢你。 - aaronburro
1
@aaronburro,我添加了一个编辑,我认为回答了你的问题 - 不完全清楚你在这里想要什么... - Reed Copsey
你的编辑很有用,几乎回答了我的问题... "can other code run between..." 应该改为 "在UI线程上,其他代码可以运行在...之间" - aaronburro
1
@aaronburro 而对于这个问题的答案是:“是的,点击窗口消息被放入消息队列中进行处理,在单击发生时排队但尚未处理的所有消息都将在单击处理之前发生。” - Scott Chamberlain

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接