Invoke()和BeginInvoke()之间有什么区别

你说的曾经没有我的故事 提交于 2020-02-28 08:05:25

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

主要是每个人将用于什么。

编辑:创建一个线程对象和调用它上面的调用,并在委托上调用BeginInvoke()有什么区别? 或者他们是一样的吗?


#1楼

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

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

一个合乎逻辑的结论是,传递给Invoke()的委托可以有out-parameters或return-value,而传递给BeginInvoke()的委托则不能(你必须使用EndInvoke来检索结果)。


#2楼

只是给出一个简短的,有效的例子来看看它们之间的差异

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


#3楼

你的意思是Delegate.Invoke / BeginInvoke还是Control.Invoke / BeginInvoke?

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

蒂姆的回答提到你可能想要使用BeginInvoke - 尽管它主要面向Delegate.BeginInvoke,我怀疑。

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

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调用,通常在回调中。


#4楼

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

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

MSDN文章


#5楼

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

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

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

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!