Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
208 views
in Technique[技术] by (71.8m points)

winforms - ConfigureAwait , UI, await async

I have a small project - WinForms On .net frameWork - just a small test :

private void button9_Click(object sender, EventArgs e)
{
    string text = GetTitleAsync().Result;
    button9.Text = text;            
}
private async Task<string> GetTitleAsync()
{
    await Task.Delay(3000);
    return "Hello!";
}

As I ran the application , Clicking the button: "button9" - caused a dead lock, (since the thread was hung on the ".result" )

Writing GetTitleAsync() this way:

private async Task<string> GetTitleAsync()
{
    await Task.Delay(3000).ConfigureAwait(false);
    return "Hello!";
}

solved the deadlock - and the application ran ok.

But I don't understand how ?

I would have expected, that using ".ConfigureAwait(false)" would cause a situation in which :

"button9.Text = text;" is executed on a different thread than the one, on which the UI was created, and an excpetion would be throwed !

but it works excellent ! how??

question from:https://stackoverflow.com/questions/65933864/configureawait-ui-await-async

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I would have expected, that using ".ConfigureAwait(false)" would cause a situation in which "button9.Text = text;" is executed on a different thread than the one, on which the UI was created, and an excpetion would be throwed ! but it works excellent ! how??

I recommend reading my async/await intro; I try to include everything you need to know about async/await and their contexts, without getting into too much detail for an intro.

Specifically, there are two points from that post that are worth noting:

  • Every async method begins executing synchronously, on the calling thread.
  • await captures a context unless you use ConfigureAwait(false).

So, walking through this code:

private void button9_Click(object sender, EventArgs e)
{
    string text = GetTitleAsync().Result;
    button9.Text = text;            
}

private async Task<string> GetTitleAsync()
{
    await Task.Delay(3000).ConfigureAwait(false);
    return "Hello!";
}

This is what happens, in order, with special attention paid to which thread runs which code:

  1. button9_Click calls GetTitleAsync() on the UI thread.
  2. GetTitleAsync() calls Task.Delay(3000) and gets back a task that will complete in 3 seconds.
  3. GetTitleAsync() calls ConfigureAwait(false) and gets back a configured awaiter that will not resume on the current (UI) context.
  4. GetTitleAsync() uses await to asynchronously wait for the task to complete. This await will not resume on the current (UI) context because the await has been configured not to.
  5. The await examines the task and sees it is not complete, so it returns an incomplete Task<string> to its caller.
  6. button9_Click calls .Result on that task. This blocks the UI thread until that task completes (i.e., GetTitleAsync() is finished executing).
  7. Three seconds later, the task returned from Task.Delay(3000) completes.
  8. GetTitleAsync() resumes executing after its await. Since this was a configured await, it continues executing on a thread pool thread.
  9. GetTitleAsync() returns "Hello!". This is done on a thread pool thread.
  10. By returning a value, GetTitleAsync() is now complete, and the Task<string> that it returned earlier is now completed with a result value. This completion also happens on a thread pool thread.
  11. Since the task is now complete, the UI thread is no longer blocked, and it continues executing button9_Click.
  12. button9_Click executes button9.Text = text; on the UI thread.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...