samodle
samodle

Reputation: 84

Async-Await Not Executing On Expected Thread

In an attempt to understand async/await I made a little sample WPF application that has one button. When clicked it will do some 'work' :

private async void goButtonClicked(object sender, EventArgs e)
        {

            WhatThreadAmI();
            var task = populateRawData().ConfigureAwait(false);
            WhatThreadAmI();
            BusyIndicator.IsBusy = true;    

            await task;
            WhatThreadAmI(); //this isnt on the main thread - why??
            BusyIndicator.IsBusy = false;

            Console.WriteLine("fin");
        }

The "WhatThreadAmI" simply compares the current thread to the UI thread which I save on initialization.

public bool IsMainThread => uiThread == Thread.CurrentThread;

I expected the output of this to be True - True - True, with the "WhatThreadAmI" call in the populate raw data method to return false.

What actually happens is True - True - False, with the ""WhatThreadAmI" call in the populate raw data method returning true.

I know I must be missing something very fundamental here, but can someone please help me understand what is going on?

Upvotes: 3

Views: 247

Answers (3)

Stephen Cleary
Stephen Cleary

Reputation: 457187

var task = populateRawData().ConfigureAwait(false);

ConfigureAwait(false) returns a configured task awaiter that does not resume on a captured context. I explain how await captures and resumes on context in detail on my blog; the usage of ConfigureAwait(false) means to not capture and resume on the context. In this case, the "context" is the UI thread. So, the await doesn't resume of the UI thread because the ConfigureAwait(false) is explicitly telling the await that it doesn't need to.

On a side note, the task variable in that code does not contain a Task. It's extremely unusual to have the result of ConfigureAwait in a variable instead of with its await. The following example is equivalent and - I think - expresses more clearly what's going on:

WhatThreadAmI();
var task = populateRawData();
WhatThreadAmI();
BusyIndicator.IsBusy = true;    

await task.ConfigureAwait(false);
WhatThreadAmI(); //this isnt on the main thread - why??
BusyIndicator.IsBusy = false;

Put another way: it's ConfigureAwait, not ConfigureTask. It doesn't change the task at all; ConfigureAwait only makes sense to use with await.

Upvotes: 4

Jeff
Jeff

Reputation: 1

change ConfigureAwait(false); to ConfigureAwait(true); or just remove it.

Upvotes: -1

David Haim
David Haim

Reputation: 26516

the Task object is an abstraction over the .Net Thread pool. one thread may begin executing code, await a not-finished task, and be resumed from a different thread.

in this way you can maximize the use of your CPU without blocking. threads have no meaning to tasks. an available thread will continue your task execution when awaiting is finished. it may be the thread which executed the task in the past, it may not.

Upvotes: 0

Related Questions