C# Invoke() 和 BeginInvoke() 有什么区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/229554/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the difference between Invoke() and BeginInvoke()
提问by Nathan W
Just wondering what the difference between BeginInvoke()
and Invoke()
are?
只是想知道BeginInvoke()
和之间Invoke()
有什么区别?
Mainly what each one would be used for.
主要是每个人的用途。
EDIT: What is the difference between creating a threading object and calling invoke on that and just calling BeginInvoke()
on a delegate? or are they the same thing?
编辑:创建线程对象并在其上调用 invoke 与仅调用BeginInvoke()
委托有什么区别?或者它们是一样的吗?
采纳答案by Jon Skeet
Do you mean Delegate.Invoke
/BeginInvoke
or Control.Invoke
/BeginInvoke
?
你是说Delegate.Invoke
/BeginInvoke
还是Control.Invoke
/ BeginInvoke
?
Delegate.Invoke
: Executes synchronously, on the same thread.Delegate.BeginInvoke
: Executes asynchronously, on athreadpool
thread.Control.Invoke
: Executes on the UI thread, but calling thread waits for completion before continuing.Control.BeginInvoke
: Executes on the UI thread, and calling thread doesn't wait for completion.
Delegate.Invoke
: 在同一个线程上同步执行。Delegate.BeginInvoke
: 在threadpool
线程上异步执行。Control.Invoke
: 在 UI 线程上执行,但调用线程在继续之前等待完成。Control.BeginInvoke
:在UI线程上执行,调用线程不等待完成。
Tim's answer mentions when you might want to use BeginInvoke
- although it was mostly geared towards Delegate.BeginInvoke
, I suspect.
蒂姆的回答提到了您可能想要使用的时间BeginInvoke
- 尽管Delegate.BeginInvoke
我怀疑它主要面向。
For Windows Forms apps, I would suggest that you should usuallyuse BeginInvoke
. That way you don't need to worry about deadlock, for example - but you need to understand that the UI may not have been updated by the time you next look at it! In particular, you shouldn't modify data which the UI thread might be about to use for display purposes. For example, if you have a Person
with FirstName
and LastName
properties, and you did:
对于 Windows 窗体应用程序,我建议您通常应该使用BeginInvoke
. 这样您就不必担心死锁,例如 - 但您需要了解在您下次查看时 UI 可能尚未更新!特别是,您不应修改 UI 线程可能将用于显示目的的数据。例如,如果您有一个Person
withFirstName
和LastName
属性,并且您做了:
person.FirstName = "Kevin"; // person is a shared reference
person.LastName = "Spacey";
control.BeginInvoke(UpdateName);
person.FirstName = "Keyser";
person.LastName = "Soze";
Then the UI may well end up displaying "Keyser Spacey". (There's an outside chance it could display "Kevin Soze" but only through the weirdness of the memory model.)
那么用户界面很可能最终会显示“Keyser Spacey”。(它有可能显示“Kevin Soze”,但只能通过内存模型的怪异。)
Unless you have this sort of issue, however, Control.BeginInvoke
is easier to get right, and will avoid your background thread from having to wait for no good reason. Note that the Windows Forms team has guaranteed that you can use Control.BeginInvoke
in a "fire and forget" manner - i.e. without ever calling EndInvoke
. This is not true of async calls in general: normally every BeginXXX should have a corresponding EndXXX call, usually in the callback.
但是,除非您遇到此类问题,否则Control.BeginInvoke
更容易解决问题,并且可以避免您的后台线程无缘无故地等待。请注意,Windows 窗体团队已保证您可以Control.BeginInvoke
以“即发即忘”的方式使用 - 即无需调用EndInvoke
. 这通常不适用于异步调用:通常每个 BeginXXX 都应该有一个相应的 EndXXX 调用,通常在回调中。
回答by Aaron Palmer
Delegate.BeginInvoke() asynchronously queues the call of a delegate and returns control immediately. When using Delegate.BeginInvoke(), you should call Delegate.EndInvoke() in the callback method to get the results.
Delegate.BeginInvoke() 异步地将委托的调用排队并立即返回控制权。使用 Delegate.BeginInvoke() 时,应在回调方法中调用 Delegate.EndInvoke() 获取结果。
Delegate.Invoke() synchronously calls the delegate in the same thread.
Delegate.Invoke() 在同一个线程中同步调用委托。
回答by Tim Stewart
Building on Jon Skeet's reply, there are times when you want to invoke a delegate and wait for its execution to complete before the current thread continues. In those cases the Invoke call is what you want.
基于 Jon Skeet 的回复,有时您想要调用委托并等待其执行完成,然后当前线程继续运行。在这些情况下, Invoke 调用就是您想要的。
In multi-threading applications, you may not want a thread to wait on a delegate to finish execution, especially if that delegate performs I/O (which could make the delegate and your thread block).
在多线程应用程序中,您可能不希望线程等待委托完成执行,特别是如果该委托执行 I/O(这可能会使委托和您的线程阻塞)。
In those cases the BeginInvoke would be useful. By calling it, you're telling the delegate to start but then your thread is free to do other things in parallel with the delegate.
在这些情况下,BeginInvoke 会很有用。通过调用它,您告诉委托开始,但随后您的线程可以自由地与委托并行执行其他操作。
Using BeginInvoke increases the complexity of your code but there are times when the improved performance is worth the complexity.
使用 BeginInvoke 会增加代码的复杂性,但有时提高的性能值得复杂性。
回答by Sujit
The difference between Control.Invoke()
and Control.BeginInvoke()
is,
Control.Invoke()
和之间的区别Control.BeginInvoke()
是,
BeginInvoke()
will schedule the asynchronous action on the GUI thread. When the asynchronous action is scheduled, your code continues. Some time later (you don't know exactly when) your asynchronous action will be executedInvoke()
will execute your asynchronous action (on the GUI thread) and wait until your action has completed.
BeginInvoke()
将在 GUI 线程上调度异步操作。调度异步操作后,您的代码将继续。一段时间后(您不知道确切时间)您的异步操作将被执行Invoke()
将执行您的异步操作(在 GUI 线程上)并等待您的操作完成。
A logical conclusion is that a delegate you pass to Invoke()
can have out-parameters or a return-value, while a delegate you pass to BeginInvoke()
cannot (you have to use EndInvoke to retrieve the results).
一个合乎逻辑的结论是,您传递给的委托Invoke()
可以有输出参数或返回值,而您传递给的委托BeginInvoke()
则不能(您必须使用 EndInvoke 来检索结果)。
回答by KMC
Just to give a short, working example to see an effect of their difference
只是举一个简短的、有效的例子来看看它们的不同之处
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");
}
If use BeginInvoke, MessageBox pops simultaneous to the text update. If use Invoke, MessageBox pops after the 3 second sleep. Hence, showing the effect of an asynchronous (BeginInvoke) and a synchronous (Invoke) call.
如果使用BeginInvoke,MessageBox 会在文本更新的同时弹出。如果使用Invoke,MessageBox 在 3 秒睡眠后弹出。因此,显示了异步 ( BeginInvoke) 和同步 ( Invoke) 调用的效果。
回答by Ingako
Just adding why and when to use Invoke().
只需添加使用 Invoke() 的原因和时间。
Both Invoke() and BeginInvoke() marshal the code you specify to the dispatcher thread.
Invoke() 和 BeginInvoke() 都将您指定的代码编组到调度程序线程。
But unlike BeginInvoke(), Invoke() stalls your thread until the dispatcher executes your code. You might want to use Invoke() if you need to pause an asynchronous operation until the user has supplied some sort of feedback.
但与 BeginInvoke() 不同的是,Invoke() 会暂停您的线程,直到调度程序执行您的代码。如果您需要暂停异步操作直到用户提供某种反馈,您可能需要使用 Invoke()。
For example, you could call Invoke() to run a snippet of code that shows an OK/Cancel dialog box. After the user clicks a button and your marshaled code completes, the invoke() method will return, and you can act upon the user's response.
例如,您可以调用 Invoke() 来运行显示确定/取消对话框的代码片段。在用户单击按钮并且您的封送代码完成后,invoke() 方法将返回,您可以根据用户的响应采取行动。
See Pro WPF in C# chapter 31
请参阅 C# 中的 Pro WPF 第 31 章