只是想知道BeginInvoke()和Invoke()之间的区别是什么?

主要是它们各自的用途。

编辑:创建线程对象和调用调用之间的区别是什么在委托上调用BeginInvoke() ?还是说它们是一样的?


当前回答

根据Jon Skeet的回答,有时候你想要调用委托,并在当前线程继续之前等待它的执行完成。在这些情况下,Invoke调用就是您想要的。

在多线程应用程序中,您可能不希望线程等待委托完成执行,特别是当委托执行I/O时(这可能会使委托和线程阻塞)。

在这些情况下,BeginInvoke会很有用。通过调用它,你告诉委托开始,然后你的线程可以自由地与委托并行做其他事情。

使用BeginInvoke会增加代码的复杂性,但有时性能的提高是值得的。

其他回答

举个简单的例子,看看它们的差异会产生什么影响

new Thread(foo).Start();

private void foo()
{
  this.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
    (ThreadStart)delegate()
    {
        myTextBox.Text = "bing";
        Thread.Sleep(TimeSpan.FromSeconds(3));
    });
  MessageBox.Show("done");
}

如果使用BeginInvoke, MessageBox会在文本更新的同时弹出。如果使用Invoke, MessageBox将在3秒休眠后弹出。因此,显示异步(BeginInvoke)和同步(Invoke)调用的效果。

根据Jon Skeet的回答,有时候你想要调用委托,并在当前线程继续之前等待它的执行完成。在这些情况下,Invoke调用就是您想要的。

在多线程应用程序中,您可能不希望线程等待委托完成执行,特别是当委托执行I/O时(这可能会使委托和线程阻塞)。

在这些情况下,BeginInvoke会很有用。通过调用它,你告诉委托开始,然后你的线程可以自由地与委托并行做其他事情。

使用BeginInvoke会增加代码的复杂性,但有时性能的提高是值得的。

只是添加为什么以及何时使用Invoke()。

Invoke()和BeginInvoke()都将您指定的代码封送到调度程序线程。

但与BeginInvoke()不同的是,Invoke()会暂停线程,直到分派器执行你的代码。如果需要暂停异步操作,直到用户提供某种反馈,则可能需要使用Invoke()。

例如,您可以调用Invoke()来运行显示OK/Cancel对话框的代码片段。在用户单击按钮并且您的封送代码完成之后,invoke()方法将返回,您可以根据用户的响应进行操作。

请参阅c#第31章中的Pro WPF

delegate . begininvoke()异步地对委托的调用进行排队,并立即返回控制。当使用Delegate.BeginInvoke()时,你应该在回调方法中调用Delegate.EndInvoke()来获得结果。

delegate . invoke()在同一个线程中同步调用委托。

MSDN文章

你是说委托吗?调用/BeginInvoke或Control.Invoke/BeginInvoke?

委托。调用:在同一个线程上同步执行。 委托。BeginInvoke:在线程池线程上异步执行。 控制。调用:在UI线程上执行,但是调用线程在继续之前等待完成。 控制。BeginInvoke:在UI线程上执行,调用线程不等待完成。

Tim的回答提到了什么时候你可能想要使用BeginInvoke——尽管它主要面向委托。我怀疑是BeginInvoke。

对于Windows窗体应用程序,我建议你通常使用BeginInvoke。这样你就不需要担心死锁,但是你需要明白UI在你下次看到它的时候可能还没有更新!特别是,您不应该修改UI线程可能用于显示目的的数据。例如,如果你有一个Person具有FirstName和LastName属性,并且你做了:

person.FirstName = "Kevin"; // person is a shared reference
person.LastName = "Spacey";
control.BeginInvoke(UpdateName);
person.FirstName = "Keyser";
person.LastName = "Soze";

然后UI很可能会显示“Keyser Spacey”。(它有很小的可能会显示“凯文·苏斯”,但这只能通过奇怪的内存模型来实现。)

除非你有这种问题,控制者。BeginInvoke更容易获得正确,并且将避免你的后台线程不得不等待没有好的理由。注意,Windows窗体团队已经保证您可以使用Control。以“触发并忘记”的方式开始调用BeginInvoke——即不调用EndInvoke。一般来说,异步调用不是这样的:通常每个BeginXXX都应该有一个相应的EndXXX调用,通常是在回调中。