views:

572

answers:

5

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 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.

+1  A: 

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.

Rex M
yes I know that, but why using Invoke my label text is refreshed and using BeginInvoke it is not
niao
@Niao see the second sentence of my answer
Rex M
A: 

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.

Taylor Leese
+2  A: 

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!

Tony
Calling BeginInvoke doesn't mean it's not executed on the UI thread. It means it's called asynchronously on the thread associated with "this" which could be the UI thread.
Taylor Leese
so if it's not in another thread, how does it work then?
Tony
From MSDN: "Executes the specified delegate asynchronously on the thread that the control's underlying handle was created on". So if it is called from the UI thread it will be placed on a queue and executed when the UI thread it idle. Which will be after the currently executing method has returned.
Justin Ethier
+4  A: 

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.

Justin Ethier
A minor point - it doesn't get executed when the method returns, it's done as a fire and forget - it's fired off into the COM/winapi ether
Chris S
Thanks for your feedback; I just updated my answer.
Justin Ethier
+2  A: 

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.
Chris S