异步编程中的同步上下文
WPF 的前端代码
<Window x:Class="Lianxi.ConfigureAwaitTest"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800">
<DockPanel>
<TextBlock Text="111" FontSize="150" x:Name="myTextBox"/>
<Button Content="点击" Width="50" Height="170" Click="Button_Click"/>
</DockPanel>
</Window>
主窗体的后端代码
public partial class ConfigureAwaitTest : Window
{
public ConfigureAwaitTest()
{
InitializeComponent();
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
await Task.Delay(3000);
var str = await Task<string>.Run(() =>
{
return "赋值成功";
}).ConfigureAwait(false);
myTextBox.Text = str;
}
}
运行起来
点击按钮就会报错,如下
当把 ConfigureAwait(true)
就不会报错了。
这里展示了如果当异步线程结束后,不回到原始上下文中,异步线程直接 操作原始上下文(UI线程)就会报错。
所以,异步操作结束是否要回到原始上下文中,要看情况而定。如果是通用库,不用考虑到UI线程,那么应该把 ConfigureAwait(false)
。否则在应用程序中,需要原始上下文进行操作的话,是需要回归原始上下文的。
当然 把 ConfigureAwait(false)。好处就是 提高性能(避免了不必要的上下文切换),也可以避免死锁的情况。
在AspNetCore 有同步上下文:SynchronizationContext.Current,
webapi 中,几乎没有UI线程,调用接口的线程都是后台线程,接口一般写的异步的方式,线程都有Task内部线程池管理,对于异步接口在await 之后使用是 可以使用 .ConfigureAwait(false)
,可提高性能。