异步等待未在预期的线程上执行
作者:互联网
为了理解异步/等待,我制作了一个带有一个按钮的小示例WPF应用程序.当点击它会做一些“工作”:
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");
}
“ WhatThreadAmI”只是将当前线程与我在初始化时保存的UI线程进行比较.
public bool IsMainThread => uiThread == Thread.CurrentThread;
我希望它的输出为True-True-True,在填充原始数据方法中使用“ WhatThreadAmI”调用返回false.
实际发生的是True-True-False,填充原始数据方法中的““ WhatThreadAmI”调用返回true.
我知道我必须在这里遗漏一些非常基本的东西,但是有人可以帮我了解发生了什么吗?
解决方法:
var task = populateRawData().ConfigureAwait(false);
ConfigureAwait(false)返回一个已配置的任务等待者,该等待者不会在捕获的上下文中恢复.我在博客上详细解释了how await
captures and resumes on context;使用ConfigureAwait(false)表示不捕获上下文并在上下文上恢复.在这种情况下,“上下文”是UI线程.因此,UI线程不会继续等待,因为ConfigureAwait(false)明确告诉等待它不需要.
另外,该代码中的task变量不包含Task.将ConfigureAwait的结果包含在变量中而不是使用其await是非常不寻常的.以下示例是等效的,并且-我认为-可以更清楚地说明正在发生的事情:
WhatThreadAmI();
var task = populateRawData();
WhatThreadAmI();
BusyIndicator.IsBusy = true;
await task.ConfigureAwait(false);
WhatThreadAmI(); //this isnt on the main thread - why??
BusyIndicator.IsBusy = false;
换句话说,它是ConfigureAwait,而不是ConfigureTask.它根本不会改变任务. ConfigureAwait仅与await一起使用才有意义.
标签:async-await,c 来源: https://codeday.me/bug/20191118/2029589.html