Loading

异步编程中的同步上下文

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;
      }
  }

运行起来
image
点击按钮就会报错,如下
image

当把 ConfigureAwait(true) 就不会报错了。
这里展示了如果当异步线程结束后,不回到原始上下文中,异步线程直接 操作原始上下文(UI线程)就会报错。
所以,异步操作结束是否要回到原始上下文中,要看情况而定。如果是通用库,不用考虑到UI线程,那么应该把 ConfigureAwait(false) 。否则在应用程序中,需要原始上下文进行操作的话,是需要回归原始上下文的。
当然 把 ConfigureAwait(false)。好处就是 提高性能(避免了不必要的上下文切换),也可以避免死锁的情况。

在AspNetCore 有同步上下文:SynchronizationContext.Current,
webapi 中,几乎没有UI线程,调用接口的线程都是后台线程,接口一般写的异步的方式,线程都有Task内部线程池管理,对于异步接口在await 之后使用是 可以使用 .ConfigureAwait(false),可提高性能。

posted @ 2024-05-07 17:20  大意了啊  阅读(3)  评论(0编辑  收藏  举报