Greetings, I am developing some application in C#. At the moment I'm dealing with threading and I have a question that I have in my mind. What is the difference between Invoke and BeginInvoke? I read some thread and I found some useful information here: here
However what is the difference between Invoke and BeginInvoke in the following code:
private void ProcessRoutine()
{
for (int nValue = StartFrom; nValue <= EndTo; nValue++)
{
this.Invoke(this.MyDelegate, nValue);
//this.BeginInvoke(this.MyDelegate, nValue);
}
MessageBox.Show("Counting complete!");
}
private void MessageHandler(int progress)
{
lblStatus.Text = lblStatus.Text = "Processing item: " + progress.ToString();
progressBar1.Value = progress;
}
where MyDelegate is a reference to MessageHandler function.
I noticed that using BeginInvoke lblStatus.Text is not refreshed where开发者_StackOverflow中文版 using Invoke refreshes the label. Additionally I know that Invoke waits for its execution to complete. The most important case I'm interested in is why there is a difference in refreshing label text in this case.
To begin, from your link:
Control.Invoke
: Executes on the UI thread, but calling thread waits for completion before continuing.Control.BeginInvoke
: Executes on the asynchronous UI thread, and calling thread doesn't wait for completion.
and from MSDN:
BeginInvoke executes the specified delegate asynchronously on the thread that the control's underlying handle was created on.
To sum it up, BeginInvoke
is asynchronous. When BeginInvoke
is called from the UI thread the request will be executed in parallel with the UI thread. Which means it may not execute until after the currently executing method has returned. So in this case the text box will never appear to update because the for loop will not be interrupted, as the calling thread will not wait for this event to be completed before continuing.
Alternatively, Invoke
is synchronous. The text box will be updated because the calling thread will wait for the call to complete before continuing execution.
With Invoke the method gets executed and the application waits for it to complete.
With BeginInvoke the method is invoked Asychnronously and the application continues to execute while the method referenced in BeginInvoke is executed.
With BeginInvoke you need to call EndInvoke to get the results of the method you executed using BeginIvnoke.
You should not update GUI components in BeginXXX methods as they are run in another thread to the GUI thread, contrary to your Invoke method. You cannot access GUI components in a different thread to the GUI thread.
Hope this helps!
Control.BeginInvoke
doesn't work on a different thread (or threadpool), a delegate.BeginInvoke does. MSDN's one liner says:
Executes the specified delegate asynchronously on the thread that the control's underlying handle was created on.
However Control.BeginInvoke
simply uses PostMessage and returns - no CLR Thread
is created.
The PostMessage function places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message.
This article summarises whether to use Invoke
or BeginInvoke
quite well:
Which function to use, you ask. It really depends on your requirement. If you want your UI update to complete before proceeding, you use Invoke. If there is no such requirement, I'd suggest using BeginInvoke, as it makes the thread calling it seemingly "faster". There are a few gotcha's with BeginInvoke though.
- If the function you are calling via BeginInvoke accesses shared state (state shared between the UI thread and other threads), you are in trouble. The state might change between the time you called BeginInvoke and when the wrapped function actually executes, leading to hard to find timing problems.
- If you are passing reference parameters to the function called via BeginInvoke, then you must make sure that no one else modifies the passed object before the function completes. Usually, people clone the object before passing it to BeginInvoke, which avoids the problem altogether.
BeginInvoke executes the method body on another thread and allows the current thread to continue. If you are trying to directly update a control property from another thread, it will throw an exception.
This basically boils down to whether or not you want the control to be updated synchronously or asynchronously. This all depends on your specific situation.
精彩评论