调用和BeginInvoking MessageBox有什么区别?

时间:2010-05-12 13:22:49

标签: c# .net winforms messagebox

在表单中,比较

BeginInvoke (new Action (() => {
    MessageBox.Show ());
}));

Invoke (new Action (() => {
    MessageBox.Show ());
}));

有什么区别,我什么时候应该使用另一个?如何通过MessageBox的消息泵来影响行为?

我做了一些测试,发现两种方法都阻止了用户界面。

唯一的区别是Invoke实际上是立即调用的,而BeginInvoke需要(非常短的)时间直到代码运行。这是可以预期的。

5 个答案:

答案 0 :(得分:16)

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将被阻止,直到消息框被解除。

答案 1 :(得分:14)

西蒙其实没错。

BeginInvoke就像向UI线程发送消息并说:“一旦有机会就这样做。”

Invoke就像是在说:“现在这样做 。我会等。”

澄清:只是因为你告诉 UI线程,“立即行动”,这并不意味着你是UI线程的上帝,并且可以强制它放弃它的一切这样做。基本上,上述陈述中的关键词是“我会等。”

问题是,在您的示例代码中,您发送到UI线程的消息是:call MessageBox.Show。你猜怎么着?这将阻止UI线程。

如果你想注意BeginInvoke的异步行为,从一个单独的线程调用它,在你的代码中调用BeginInvoke之后放一个断点,并注意断点即使在将显示消息框(并且UI已被阻止)。如果您致电Invoke,则在用户取消消息框之前,代码将不会继续。

答案 2 :(得分:3)

BeginInvoke是异步的...这意味着调用线程不会等待被调用的方法返回。

好吧,对话框总是冻结GUI。但是现在应该清楚开始调用和调用之间的区别:

Invoke等待被调用的方法返回 BeginInvoke没有。

答案 3 :(得分:2)

虽然大部分答案在技术上都是正确的,但他们并没有提出明显的问题。

为什么要首先在Invoke / BeginOnvoke中包装MessageBox()调用?

在Jeff的解释中,在这种情况下使用BeginInvoke或Invoke没有任何好处。

听起来你在多线程情况下在Windows窗体/控件上使用Invoke / BeginInvoke,在委托实例上使用Invoke / BeginInvoke(即异步编程模型)时感到困惑。

这很容易做,因为名称显然是相同的,但是你使用它们的场景和它们的行为是不同的。

本书CLR Via C#很好地解释了两种类型的Invoke / BeginInvoke。

答案 4 :(得分:1)

对于MessageBox.Show,问题大多无关紧要。

唯一的区别在于使用BeginInvoke,调用线程本身不会阻塞,因此它可以继续处理(清理,进一步处理等)。

UI线程显然会阻塞,因为会弹出一个模态窗口,等待用户输入关闭它。