Answers:
你是说Delegate.Invoke
/ BeginInvoke
还是Control.Invoke
/ BeginInvoke
?
Delegate.Invoke
:在同一线程上同步执行。Delegate.BeginInvoke
:在threadpool
线程上异步执行。Control.Invoke
:在UI线程上执行,但是调用线程在继续之前等待完成。Control.BeginInvoke
:在UI线程上执行,并且调用线程不等待完成。蒂姆(Tim)的答案提到了您可能想使用的时间BeginInvoke
- Delegate.BeginInvoke
我怀疑,尽管它主要是针对的。
对于Windows Forms应用程序,我建议您通常使用BeginInvoke
。这样,您就不必担心死锁了-但是您需要了解,在下次查看UI时可能尚未更新UI!特别是,您不应修改UI线程可能要用于显示目的的数据。例如,如果您具有Person
with 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”。(有外部机会显示“ Kevin Soze”,但只能通过内存模型的怪异来显示。)
但是,除非您遇到此类问题,否则Control.BeginInvoke
更容易解决问题,并且可以避免后台线程无缘无故地等待。请注意,Windows Forms团队已保证您可以Control.BeginInvoke
“一劳永逸”的方式使用-即无需致电EndInvoke
。通常,异步调用不是这样:通常每个BeginXXX应该在回调中有一个对应的EndXXX调用。
只是给出一个简短的示例,以了解它们之间的差异所产生的影响
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,则在睡眠3秒后会弹出MessageBox。因此,显示了异步(BeginInvoke)和同步(Invoke)调用的效果。
Delegate.BeginInvoke()异步将委托的调用排队,并立即返回控件。使用Delegate.BeginInvoke()时,应在回调方法中调用Delegate.EndInvoke()以获取结果。
Delegate.Invoke()在同一线程中同步调用委托。