8

I am trying to understand how async/await keywords works. I have a textblock on a WPF window bind to a TextBlockContent string property and a button which trigger on click ChangeText().

Here is my code :

public async void ChangeText()
{
     string mystring = await TestAsync();
     this.TextBlockContent= mystring;
}

private async Task<string> TestAsync()
{
     var mystring = await GetSomeString().ConfigureAwait(false);
     mystring = mystring + "defg";
     return mystring;
}

private Task<string> GetSomeString()
{
    return Task.Run(() =>
    {
        return "abc";
    });
}

From my readings, I understood that ConfigureAwait set to false would allow me to specify that I do not want to save the Current context for the "rest" of the Task that needs to be executed after the await keyword.

After debugging i realize that when i have this code, sometime the code is running on the Main thread after the line : await GetSomeString().ConfigureAwait(false); while i specifically added the configure await.

I would have expected it to always run on a different thread that the one it was in before it entered the Task.

Can someone help me understand why?

Thank you very much

K. L.
  • 654
  • 2
  • 10
  • 21
  • My 2 cents: if you really want to make sure you continue on a new thread after `await`, you can with a [custom awaiter](http://stackoverflow.com/questions/18779393/the-lack-of-non-capturing-task-yield-forces-me-to-use-task-run-why-follow-that). This is considered a bad practice, though. – noseratio Oct 20 '13 at 09:09

1 Answers1

13

It could well be that the task you're running is completing immediately - which means that the await doesn't even need to schedule a continuation. An async method only schedules a continuation when it needs to; if you await something which has already completed, it just keeps going - in the same thread.

ConfigureAwait is a hint that you don't need to continue in the same context; it's not a requirement that you mustn't continue on the same context.

If you change your task to something that doesn't complete immediately - e.g. call Thread.Sleep(1000) (which of course you wouldn't normally do) I'd expect you to see a change in behaviour.

It's possible that I've missed something else and that this isn't the cause of the problem, but it would at least be worth trying that first.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Well it seems to be that. I knew that the scheduler wouldn't schedule a task if already completed like Task.FromResult(...) but i didn't know that if the execution is almost "instant" it would consider it directly completed. Thanks for the explanation ! – K. L. Oct 19 '13 at 20:08
  • 1
    @Alexei: No, I mean Thread.Sleep. The point is to create a task which doesn't complete quickly. Sleeping is an easy way of doing that. – Jon Skeet Oct 19 '13 at 20:13
  • Right... OP starts new task. My comment would make sense if it would be part of the `async` method, not `Task.Run`. – Alexei Levenkov Oct 19 '13 at 20:38