我正在研究其他人的代码,并且对与多线程有关的任何事情都没有太多经验。我遇到了这行代码:
BeginInvoke((MethodInvoker)delegate() { btnCalibrate.PerformClick(); });
我想知道为什么这样做会起作用:btnCalibrate.PerformClick();
感谢您的回答。
我正在研究其他人的代码,并且对与多线程有关的任何事情都没有太多经验。我遇到了这行代码:
BeginInvoke((MethodInvoker)delegate() { btnCalibrate.PerformClick(); });
我想知道为什么这样做会起作用:btnCalibrate.PerformClick();
感谢您的回答。
因为如果此代码在与在 GUI 中创建按钮的线程不同的线程中运行,则会引发异常。后台线程不能直接调用 GUI 上的方法,因为 GUI 不是线程安全的。
当然,这只是使用的合理理由BeginInvoke
!但是,发现包含无缘无故输入的咒语或魔法咒语的代码并不罕见,因为作者看到了另一个这样做的例子,因此假设在所有情况下都必须这样做。如果您正在使用的代码是单线程的,那么就没有必要了。
尤其是 Windows 窗体本身是绝对单线程的。所有窗口和控件上的所有操作都发生在同一个线程上,并且它们的所有事件都在同一个线程上触发。一个 GUI 线程的使用是通过一个在线程上连续运行并从队列中读取消息的消息循环来划分的。BeginInvoke 的最终目的是向该队列发布一条消息,有效地说“当你有时间时,请运行这段代码”。
稍微扩展@Earwicker - Control.BeginInvoke 是一种将调用从一个线程转移到拥有 Control 实例的线程的方法。在后台,它通过调用的 Win32 函数使用 Win32 消息PostMessage
来编组对PerformClick
拥有线程上的方法的调用。由于 Win32 Windows 和扩展 WinForms 控件,这是必需的,只能从创建它的线程安全访问,这通常是运行 GUI 的单线程。
之所以BeginInvoke
使用vs.Invoke
是因为前者使用PostMessage
并立即返回,而后者在幕后使用SendMessage
,需要等待PostMessage
并等待GUI线程的回复。这可能会延迟进行调用的线程甚至锁定应用程序,因此BeginInvoke
这里是更好的选择。