考虑以下 Windows 窗体代码:
private async void UpdateUIControlClicked(object sender, EventArgs e)
{
this.txtUIControl.Text = "I will be updated after await - i hope!";
await Task.Delay(5000).ConfigureAwait(continueOnCapturedContext: false);
this.txtUIControl.Text = "I am updated now.";
}
这里在第 3 行抛出异常,因为在等待之后代码在非 UI 线程上执行。
ConfigureAwait(false) 在哪里有用?
Stephen Cleary 在这方面有一个非常好的系列,你可以在这里找到,我引用了针对您的问题的那篇文章:
大多数时候,你不need同步回“主”上下文。大多数异步方法在设计时都会考虑到组合:它们等待其他操作,并且每个方法本身都代表一个异步操作(可以由其他操作组合)。在这种情况下,你想告诉服务员not通过调用捕获当前上下文配置等待并经过false
, e.g.:
private async Task DownloadFileAsync(string fileName)
{
// Use HttpClient or whatever to download the file contents.
var fileContents = await DownloadFileContentsAsync(fileName).ConfigureAwait(false);
// Note that because of the ConfigureAwait(false), we are not on the original context here.
// Instead, we're running on the thread pool.
// Write the file contents out to a disk file.
await WriteToDiskAsync(fileName, fileContents).ConfigureAwait(false);
// The second call to ConfigureAwait(false) is not *required*, but it is Good Practice.
}
// WinForms example (it works exactly the same for WPF).
private async void DownloadFileButton_Click(object sender, EventArgs e)
{
// Since we asynchronously wait, the UI thread is not blocked by the file download.
await DownloadFileAsync(fileNameTextBox.Text);
// Since we resume on the UI context, we can directly access UI elements.
resultTextBox.Text = "File downloaded!";
}
此示例中需要注意的重要一点是,异步方法调用的每个“级别”都有其自己的上下文。DownloadFileButton_Click
在 UI 上下文中启动,并调用DownloadFileAsync
. DownloadFileAsync
也是在 UI 上下文中启动,但随后通过调用退出其上下文ConfigureAwait(false)
。其余的DownloadFileAsync
在线程池上下文中运行。然而,当DownloadFileAsync
完成并且DownloadFileButton
_点击简历,就可以了does在 UI 上下文中恢复。
一个好的经验法则是使用ConfigureAwait(false)
除非你认识你do需要上下文。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)