异步编程基础

异步编程基础

异步编程基础

  1. 死锁

    • ConfigureAwait 的作用?

      试图继续回夺取的原始上下文,则为 true;否则为 false

    • 什么情况下会造成死锁?

      同步方法中调用异步方法,异步方法或异步方法中的异步方法(指 Task ),没有使用 .ConfigureAwait(false)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      > [Route("")]
      > [HttpGet]
      > public string Index()
      > {
      > System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId1:" + Thread.CurrentThread.ManagedThreadId);
      > var result = Test3().Result;
      > System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId4:" + Thread.CurrentThread.ManagedThreadId);
      > return result;
      > }
      >
      > public static async Task<string> Test3()
      > {
      > System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId2:" + Thread.CurrentThread.ManagedThreadId);
      > using (var client = new HttpClient())
      > {
      > var response = await client.GetAsync(url);
      > System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId3:" + Thread.CurrentThread.ManagedThreadId);
      > return await response.Content.ReadAsStringAsync();
      > }
      > }
      >

      输出结果:

      1
      2
      3
      > Thread.CurrentThread.ManagedThreadId1:5
      > Thread.CurrentThread.ManagedThreadId2:5
      >

      Test3().Result会阻塞主线程,等待Test3()中的线程执行完毕,会到主线程。Test3()中 await client.GetAsync(url), 会尝试获取当前线程上下文,这个上下文正在被主线程占用,并未释放,至此互相等待引起死锁。更正为 await client.GetAsync(url).ConfigureAwait(false),会从线程池获取线程上下文,可避免这种情况。

      .ConfigureAwait(false),从线程池里获取新的线程,取消对SynchronizationContext的竞争。 .ConfigureAwait(true),与主线程竞争SynchronizationContext

      特别注意:.net core 取消了SynchronizationContext,不再有死锁