调用和BeginInvoking MessageBox有什么区别?
在表格中,比较
BeginInvoke (new Action (() => { MessageBox.Show ()); }));
同
Invoke (new Action (() => { MessageBox.Show ()); }));
有什么区别,什么时候应该使用一个而不是另一个? 如何通过MessageBox的消息泵来影响行为?
我做了一些测试,发现两种方法都阻止了UI。
唯一的区别是Invoke实际上是立即调用的,而BeginInvoke需要(非常短的)时间直到代码运行。 这是可以预料的。
BeginInvoke
将异步调用委托,立即返回将委托排队以便独立于当前线程执行。
Invoke
将同步调用委托,阻塞调用线程,直到委托完成。
要查看差异,请尝试以下代码:
BeginInvoke(new Action(()=>Console.WriteLine("BeginInvoke"))); Console.WriteLine("AfterBeginInvokeCalled"); Invoke(new Action(()=>Console.WriteLine("Invoke"))); Console.WriteLine("AfterInvokeCalled");
您应该看到类似于以下内容的输出,其中“BeginInvoke”文本由于其异步执行而延迟:
AfterBeginInvokeCalled
调用
AfterInvokeCalled
的BeginInvoke
关于您观察到的行为,因为它只是调用委托的同步或异步行为; 该方法的内容可能会导致调用线程停止或UI被阻止。 在显示消息框的情况下,无论委托是否使用BeginInvoke
延迟,一旦调用委托,UI将被阻止,直到消息框被解除。
西蒙其实没错。
BeginInvoke
就像向UI线程发送消息并说:“一旦有机会就这样做。”
Invoke
就像是在说:“ 现在就这样做。我会等。”
澄清:只是因为你告诉 UI线程,“立即行动”,这并不意味着你是UI线程的上帝,并且可以强迫它放弃它正在做的一切。 基本上,上述陈述中的关键词是“我会等”。
问题是,在您的示例代码中,您发送到UI线程的消息是:调用MessageBox.Show
。 你猜怎么着? 这将阻止UI线程。
如果你想要注意BeginInvoke
的异步行为,从一个单独的线程调用它,在代码中的BeginInvoke
调用之后放置一个断点,并注意到即使在显示消息框时(并且UI被阻止),断点也会被命中。 如果您调用Invoke
,代码将不会继续,直到用户解除消息框。
BeginInvoke是异步的……这意味着调用线程不会等待被调用的方法返回。
好吧,对话框总是冻结GUI。 但是现在应该清楚begin invoke和invoke之间的区别:
调用等待被调用的方法返回BeginInvoke没有。
虽然大多数答案在技术上是正确的,但他们并没有提出明显的问题。
为什么要首先在Invoke / BeginOnvoke中包装MessageBox()调用?
Jeff解释说,在这种情况下使用BeginInvoke或Invoke没有任何好处。
听起来你在multithreading情况下在Windows窗体/控件上使用Invoke / BeginInvoke,在委托实例上使用Invoke / BeginInvoke(即异步编程模型)时感到困惑。
这很容易做,因为名称显然是相同的,但是您使用它们的场景和它们的行为是不同的。
CLR Via C#一书很好地解释了两种类型的Invoke / BeginInvoke。
对于MessageBox.Show,问题大多无关紧要。
唯一的区别是,使用BeginInvoke, 调用线程本身不会阻塞,因此它可以继续处理(清理,进一步处理等)。
UI线程显然会阻塞,因为会弹出一个模态窗口,等待用户输入关闭它。