TTGroup
TTGroup

Reputation: 3713

Control.Dispatcher.BeginInvoke() and Control.Dispatcher.Invoke() order execution is confusing?

I'm using WPF, and I was confused about the order of execution Control.Dispatcher.BeginInvoke() and Control.Dispatcher.Invoke().

I will show an example of code below

backgroundThread = new Thread(BackgroundThread);
backgroundThread.Start();
public void BackgroundThread()
{
    this.Dispatcher.BeginInvoke(new Action(delegate()
    {
      WriteLog("Run command 1");
    }));

    this.Dispatcher.Invoke(new Action(delegate()
    {
      WriteLog("Run command 2");
    }));
}

I expect the "Command 1" will be run and finished before "command 2", but sometimes It seems the "Command 2" run before "Command 1". I have researched much on internet and MSDN document, but I don't understand why this happen.

Someone please tell me the rule of these functions exactly?

Many thanks!

T&T

Upvotes: 6

Views: 2126

Answers (4)

Ethan Wang
Ethan Wang

Reputation: 98

well, i think sniffer's answer is pretty clear enough. basiclly you get almost all the idea here, the last thing may need your orgnize those concepts.

1, the Invoke here you called will switch the current main thread execution to the UI thread synchronously, of course, if it's a loooong running, will block the main thread until your invoke code completion; 2, The difference of BeginInvoke is that this switch happens asynchronously, wouldn't affect the main thread.

and i assume you already understand why the output sequence

Upvotes: 2

Ehsan
Ehsan

Reputation: 32721

Someone please tell me the rule of these functions exactly

Following is the diffrence

Dispatcher.Invoke: Executes the specified delegate synchronously on the thread the Dispatcher is associated with
Dispatcher.BeginInvoke: Executes the specified delegate asynchronously on the thread the Dispatcher is associated with..

and now your understanding

I expect the "Command 1" will be run and finished before "command 2", but sometimes It seems the "Command 2" run before "Command 1"

As your first call is Asynchronous so it may finish before or after your second call (which is synchronous).

Upvotes: 2

Haris Hasan
Haris Hasan

Reputation: 30117

I expect the "Command 1" will be run and finished before "command 2", but sometimes It seems the "Command 2" run before "Command 1".

Your assumption is wrong because Control.BeginInvoke runs asynchronously while the Control.Invoke runs synchronously.

If you want to make sure command 1 runs before command 2, run command 1 using Invoke.

When you use BeginInvoke you are not getting the order guarantee because it's upto Dispatcher when it's going to execute it.

Upvotes: 1

Ibrahim Najjar
Ibrahim Najjar

Reputation: 19423

BeginInvoke calls the Action you pass to it asynchronously on the thread that is associated with the Dispatcher while Invoke calls that action synchronously.

In other words, Invoke immediately executes what ever Action you pass to it while BeginInvoke puts the action you pass to it on the Dispatcher queue which is like a list of the things the Dispatcher is going to do but with no guarantee when that is going to happen or as soon as the dispatcher has finished doing the other things waiting on that queue.

So sometimes the Dispatcher might be busy doing something else and puts the action you pass to BeginInvoke on the queue's end until it can execute it, and then it executes whatever action you pass to Invoke immediately and that is the reason for the order differences.

Upvotes: 7

Related Questions