424

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

主要是每个人的用途。

BeginInvoke()编辑:创建线程对象和调用调用和调用委托之间有什么区别?还是它们是同一回事?

4

6 回答 6

609

你是说Delegate.Invoke/BeginInvoke还是Control.Invoke/ BeginInvoke

  • Delegate.Invoke:在同一个线程上同步执行。
  • Delegate.BeginInvoke:在threadpool线程上异步执行。
  • Control.Invoke:在 UI 线程上执行,但调用线程在继续之前等待完成。
  • Control.BeginInvoke:在 UI 线程上执行,调用线程不等待完成。

蒂姆的回答提到了您可能想要使用的时间BeginInvoke- 尽管我怀疑它主要面向Delegate.BeginInvoke.

对于 Windows 窗体应用程序,我建议您通常应该使用BeginInvoke. 例如,这样您就不必担心死锁 - 但您需要了解,当您下次查看 UI 时,它可能尚未更新!特别是,您不应修改 UI 线程可能将用于显示目的的数据。例如,如果你有一个PersonwithFirstNameLastName属性,你做了:

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

然后 UI 很可能最终会显示“Keyser Spacey”。(有一个外部机会它可以显示“Kevin Soze”,但只能通过记忆模型的怪异。)

但是,除非您遇到此类问题,否则Control.BeginInvoke更容易解决问题,并且可以避免您的后台线程无缘无故地等待。请注意,Windows 窗体团队已保证您可以Control.BeginInvoke以“即发即弃”的方式使用 - 即无需调用EndInvoke. 一般来说,异步调用并非如此:通常每个 BeginXXX 都应该有一个对应的 EndXXX 调用,通常在回调中。

于 2008-10-23T12:40:02.747 回答
53

基于 Jon Skeet 的回复,有时您想要调用委托并等待其执行完成,然后再继续当前线程。在这些情况下,调用调用就是您想要的。

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

在这些情况下,BeginInvoke 会很有用。通过调用它,您是在告诉委托开始,但是您的线程可以自由地与委托并行执行其他操作。

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

于 2008-10-23T12:49:49.360 回答
32

Control.Invoke()和之间的区别Control.BeginInvoke()是,

  • BeginInvoke()将在 GUI 线程上安排异步操作。安排异步操作后,您的代码将继续。一段时间后(您不知道确切的时间)您的异步操作将被执行
  • Invoke()将执行您的异步操作(在 GUI 线程上)并等待您的操作完成。

一个合乎逻辑的结论是,您传递给的委托Invoke()可以具有输出参数或返回值,而您传递给的委托BeginInvoke()则不能(您必须使用 EndInvoke 来检索结果)。

于 2012-09-11T07:07:32.857 回答
23

只是给出一个简短的工作示例,以了解它们的差异的影响

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 ) 调用的效果。

于 2012-12-14T05:11:39.043 回答
10

Delegate.BeginInvoke() 将委托的调用异步排队并立即返回控制权。使用 Delegate.BeginInvoke() 时,应在回调方法中调用 Delegate.EndInvoke() 以获取结果。

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

MSDN 文章

于 2008-10-23T12:47:01.080 回答
10

只需添加使用 Invoke() 的原因和时间。

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

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

例如,您可以调用 Invoke() 来运行一段显示 OK/Cancel 对话框的代码。在用户单击按钮并且您的编组代码完成后,invoke() 方法将返回,您可以根据用户的响应采取行动。

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

于 2015-01-06T04:28:15.717 回答