我真的很尴尬地问这么简单的问题,但调试一些软件现在说服我,我真的不明白这个问题:
如何在20,000英尺高度看到.NET事件?我不是指委托/事件处理程序模式和所有这些。我的意思是 - 什么是大图:
现在,魔术是什么?这与线程有什么关系?当事件发生时,运行我的代码的线程是否被中断,然后在事件处理程序返回后恢复?但我用google搜索并found out在原始线程中同步调用.NET处理程序。那么谁负责停止和恢复代码A?如果事件是嵌套的(即事件1的事件处理程序正在运行时发生事件2)会发生什么?
编辑:据我所知,答案表示 next 事件的事件处理只会在当前运行的事件处理程序完成后才会运行。这意味着您的代码不会被中断:第n行将始终在第n-1行之后和第n + 1行之前立即运行。然而就在我发布问题之前,我正在调试程序,通过自动化控制Internet Explorer(使用Webius的SWExplorerAutomation)。我非常肯定,当我在代码中踩线时,我被“绑架”:-)到一些事件处理程序,并在事件处理程序完成其业务后返回到代码中的中断位置。这意味着要么不理解答案,要么在逐步通过调试器时程序的行为不同!
答案 0 :(得分:3)
让我谈谈你的问题。神奇的是Windows消息循环。实际上,在您的示例中看到,当事件发生时,没有任何代码可以使代码A停止。相反,这是序列。
当代码A运行时,用户单击一个按钮。按钮的窗口消息排队,但没有任何反应。当代码A退出其功能或将控制权交还给消息循环时,将处理Click事件并运行事件处理程序。
试试这个实验。在主线程的程序中放入一个无限循环,然后单击用户界面。您会注意到用户界面没有响应,并且没有运行事件处理程序。
答案 1 :(得分:2)
你将在20,000英尺处看到的东西是 MessageLoop 。它在Application.Run()
内。
简单地说,这是一个运行应用程序整个生命周期的while循环
// pseudo code, I did not reflector Application.Run
while (GetMessage(ref msg)
{
DispatchMessage(ref msg);
}
当您处理太长的处理1事件时,您将注意到simgle-thread,您的应用程序将在TaskManager中标记为“无响应”。
相关方法是Application.DoEvents()
,但请远离此方法。
答案 2 :(得分:1)
事件是函数的指针(就像我们以前在C ++中一样)。当您使用普通的vanilla .NET事件时,您实际上正在调用使用+ =连接到该事件的函数。因此,从20,000英尺开始,您的代码实际上调用其他代码就像调用另一个函数一样 这就是它在同一个线程中同步调用的原因。
当在WinForms / WPF控件内部时,我们还有一个消息循环要考虑: 在表单上下文中发生的所有事件都会向消息循环添加消息,而不是直接调用方法。
控件的主线程轮询该循环以获取新消息,并且当出现新消息时,他执行它(再次在主线程中),现在它不是完全同步的。
这就是为什么如果表单忙于做某事并按下按钮,则按下该按钮需要一些时间。这也是为什么如果你使一个控件无效,它的外观只有在你退出正在运行的方法后才会改变(并处理下一条消息)。