What's the difference between Invoke() and BeginInvoke()
Do you mean Delegate.Invoke
/BeginInvoke
or 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.
Tim's answer mentions when you might want to use BeginInvoke
- although it was mostly geared towards Delegate.BeginInvoke
, I suspect.
For Windows Forms apps, I would suggest that you should usually use 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:
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.)
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.
What is the difference between Invoking and BeginInvoking a MessageBox?
BeginInvoke
will invoke the delegate asynchronously, returning immediately having queued the delegate for execution independently of the current thread.
Invoke
will invoke the delegate synchronously, blocking the calling thread until the delegate completes.
To see the difference, try the following code:
BeginInvoke(new Action(()=>Console.WriteLine("BeginInvoke")));
Console.WriteLine("AfterBeginInvokeCalled");
Invoke(new Action(()=>Console.WriteLine("Invoke")));
Console.WriteLine("AfterInvokeCalled");
You should see output similar to the following, where the "BeginInvoke" text is delayed due to its asynchronous execution:
AfterBeginInvokeCalled
Invoke
AfterInvokeCalled
BeginInvoke
Regarding the behaviour you observe, as it is only the act of calling the delegate that is synchronous or asynchronous; the content of the method may well cause the calling thread to stop or the UI to be blocked. In the case of showing a message box, regardless of whether the delegate is delayed using BeginInvoke
or not, once the delegate is called, the UI will be blocked until the message box is dismissed.
Invoke and BeginInvoke
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!
Dispatcher Invoke(...) vs BeginInvoke(...) confusion
When you use Dispatcher.BeginInvoke
it means that it schedules the given action for execution in the UI thread at a later point in time, and then returns control to allow the current thread to continue executing. Invoke
blocks the caller until the scheduled action finishes.
When you use BeginInvoke
your loop is going to run super fast since BeginInvoke
returns right away. This means that you're adding lot and lots of actions to the message queue. You're adding them much faster than they can actually be processed. This means that there's a long time between when you schedule a message and when it actually gets a chance to be run.
The actual action that you're running uses the field _number
. But _number
is being modified by the other thread very quickly and while the action is in the queue. This means that it won't display the value of _number
at the time you scheduled the action, but rather what it is after it has been continuing on in it's very tight loop.
If you use Dispatcher.Invoke
instead then it prevents the loop from "getting ahead of itself" and having multiple scheduled events, which ensures that the value that it's writing is always the "current" value. Additionally, by forcing each iteration of the loop to wait for the message to be run it makes the loop a lot less "tight", so it can't run as quickly in general.
If you want to use BeginInvoke
the first thing you really need to do is slow down your loop. If you want it to update the text every second, or ever 10ms, or whatever, then you can use Thread.Sleep
to wait the appropriate amount of time.
Next, you need to take a copy of _number
before passing it to the Dispatcher
so that it displays the value at the time you scheduled it, not at the time it is executed:
while (true)
{
if (_number++ > 10000)
_number = 0;
int copy = _number;
this.Dispatcher.BeginInvoke(new Action(() => UpdateText(copy))
, System.Windows.Threading.DispatcherPriority.Background, null);
Thread.Sleep(200);
}
private void UpdateText(int number)
{
this.Text = number.ToString();
}
Control.Invoke() vs. Control.BeginInvoke()
Yes, it will be executed on the dispatcher of the UI thread that created it.
As for creating a control on a background thread, I wouldn't advise it. Furthermore, you haven't mentioned what technology you are working with.
What is difference between Control.BeginInvoke() and Dispatcher.BeginInvoke()?
Control.BeginInvoke
existed from the early days of .NET (at least version 1.1). This is a very natural fit if you have an control and want to run something on its UI thread (there can be several UI threads). However if you wanted to run something general on the UI thread and didn't have an appropriate Control
the hacky solution was to create a Control
which doesn't appear in the UI and then Invoke
on that.
In .NET 3 (IIRC) Dispatcher
was added to solve this problem.
In short:
- If you have a
Control
at hand you can useControl.BeginInvoke
- If you don't have an appropriate control, create a
Dispatcher
(in advance) and useDispatcher.BeginInvoke
- If you're in the distant past, you have no option but to use
Control.BeginInvoke
:)
What's the difference between InvokeAsync and BeginInvoke for WPF Dispatcher
There are no differences as the BeginInvoke
method calls a private LegacyBeginInvokeImpl
method which itslef calls the private method InvokeAsyncImpl
(the method used by InvokeAsync
). So it's basically the same thing. It seems like it's a simple refactoring, however it's strange the BeginInvoke
methods weren't flagged as obsolete.
BeginInvoke :
public DispatcherOperation BeginInvoke(DispatcherPriority priority, Delegate method)
{
return this.LegacyBeginInvokeImpl(priority, method, null, 0);
}
private DispatcherOperation LegacyBeginInvokeImpl(DispatcherPriority priority, Delegate method, object args, int numArgs)
{
Dispatcher.ValidatePriority(priority, "priority");
if (method == null)
{
throw new ArgumentNullException("method");
}
DispatcherOperation dispatcherOperation = new DispatcherOperation(this, method, priority, args, numArgs);
this.InvokeAsyncImpl(dispatcherOperation, CancellationToken.None);
return dispatcherOperation;
}
InvokeAsync :
public DispatcherOperation InvokeAsync(Action callback, DispatcherPriority priority)
{
return this.InvokeAsync(callback, priority, CancellationToken.None);
}
public DispatcherOperation InvokeAsync(Action callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
if (callback == null)
{
throw new ArgumentNullException("callback");
}
Dispatcher.ValidatePriority(priority, "priority");
DispatcherOperation dispatcherOperation = new DispatcherOperation(this, priority, callback);
this.InvokeAsyncImpl(dispatcherOperation, cancellationToken);
return dispatcherOperation;
}
Related Topics
Recursion, Parsing Xml File With Attributes into Treeview C#
When Correctly Use Task.Run and When Just Async-Await
How to Read a CSV File into a .Net Datatable
Json.Net: How to Deserialize Without Using the Default Constructor
Memory Leak Using Streamreader and Xmlserializer
Is There a Better Alternative Than This to 'Switch on Type'
Listen For Key Press in .Net Console App
What Is the Yield Keyword Used For in C#
In .Net, Which Loop Runs Faster, 'For' or 'Foreach'
Unity Scripts Edited in Visual Studio Don't Provide Autocomplete
The Provider Is Not Compatible With the Version of Oracle Client