<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      C#異步編程由淺入深(三)細(xì)說Awaiter

      ??上一篇末尾提到了Awaiter這個(gè)類型,上一篇說了,能await的對(duì)象,必須包含GetAwaiter()方法,不清楚的朋友可以看上篇文章。那么,Awaiter到底有什么特別之處呢?
      ??首先,從上篇文章我們知道,一個(gè)Awaiter必須實(shí)現(xiàn)INotifyCompletion接口,這個(gè)接口定義如下:

      namespace System.Runtime.CompilerServices
      {
          /// <summary>
          /// Represents an operation that will schedule continuations when the operation completes.
          /// </summary>
          public interface INotifyCompletion
          {
              /// <summary>Schedules the continuation action to be invoked when the instance completes.</summary>
              /// <param name="continuation">The action to invoke when the operation completes.</param>
              /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
              void OnCompleted(Action continuation);
          }
      }
      

      ??除此之外還必須包含IsCompleted屬性和包含GetResult()方法。
      ??注意OnCompleted的參數(shù)是一個(gè)Action委托,并且不出意外的話,委托里面總會(huì)有一個(gè)地方調(diào)用一個(gè)MoveNext()方法,它推動(dòng)狀態(tài)機(jī)到達(dá)下一個(gè)狀態(tài),然后執(zhí)行下一個(gè)狀態(tài)需要執(zhí)行的代碼。
      ??那么,知道這個(gè)有什么用呢?第一,它是你充分了解async/await這套機(jī)制的基礎(chǔ),包括與之相關(guān)的同步上下文、執(zhí)行上下文、死鎖問題等,第二,它可以實(shí)現(xiàn)一些特殊的功能。
      ??從上一篇我們知道,OnCompleted中的contination的主要目的是推動(dòng)狀態(tài)機(jī)的執(zhí)行,也就是推動(dòng)異步方法中await后面部分的代碼執(zhí)行。從這里看出,continuation的執(zhí)行是受我們控制的,因此我們可以直接執(zhí)行它,或是等待某個(gè)條件成熟然后執(zhí)行它,我們可以把它放到線程池執(zhí)行,也可以單獨(dú)起一個(gè)線程執(zhí)行。譬如,我們可以讓await后面部分的代碼直接在線程池上執(zhí)行。

      public static async Task AwaiterTest()
      {
          Console.WriteLine($"是否是線程池線程?{Thread.CurrentThread.IsThreadPoolThread}");
          await default (SkipToThreadPoolAwaiter);
          Console.WriteLine($"是否是線程池線程?{Thread.CurrentThread.IsThreadPoolThread}");
      }
      
      static void Main(string[] args)
      {
          _ = AwaiterTest();
          Console.ReadLine();
      }
      
      public struct SkipToThreadPoolAwaiter : INotifyCompletion
      {
          public bool IsCompleted => false;
          public void GetResult() 
          {
              Console.WriteLine("調(diào)用GetResult以獲取結(jié)果");
          }
          public void OnCompleted(Action continuation)
          {
              Console.WriteLine("調(diào)用OnCompleted,把Await后面部分要執(zhí)行的代碼傳遞過來(傳遞MoveNext,以推動(dòng)狀態(tài)機(jī)流轉(zhuǎn))");
              ThreadPool.QueueUserWorkItem(state =>
              {
                  Console.WriteLine("開始執(zhí)行Await后面部分的代碼");
                  continuation();
                  Console.WriteLine("后面部分的代碼執(zhí)行完畢");
              });
              Console.WriteLine("返回調(diào)用線程");
          }
      
          public SkipToThreadPoolAwaiter GetAwaiter()
          {
              Console.WriteLine("獲得Awaiter");
              return this;
          }
      }
      

      ??這是一個(gè)控制臺(tái)程序,輸出結(jié)果如下。

      是否是線程池線程?False
      獲得Awaiter
      調(diào)用OnCompleted,把Await后面部分要執(zhí)行的代碼傳遞過來(傳遞MoveNext,以推動(dòng)狀態(tài)機(jī)流轉(zhuǎn))
      返回調(diào)用線程
      開始執(zhí)行Await后面部分的代碼
      調(diào)用GetResult以獲取結(jié)果
      是否是線程池線程?True
      后面部分的代碼執(zhí)行完畢
      

      ??特別注意一下,第五步說明可能有點(diǎn)疑惑,怎么第六步不是打印是否是線程池線程?原因是部分awaiter是有返回值的,在執(zhí)行await后面部分的代碼時(shí),會(huì)首先調(diào)用GetResult()以獲取結(jié)果。這對(duì)編譯器改造異步方法來說是一個(gè)固定的模式(上篇文章沒有體現(xiàn)這一步)。
      ??把Awaiter改成有返回值嘗試。

      public static async Task AwaiterTest()
      {
          Console.WriteLine($"是否是線程池線程?{Thread.CurrentThread.IsThreadPoolThread}");
          var res = await default (SkipToThreadPoolAwaiter);
          Console.WriteLine($"結(jié)果是{res}");
          Console.WriteLine($"是否是線程池線程?{Thread.CurrentThread.IsThreadPoolThread}");
      }
      
      static void Main(string[] args)
      {
          _ = AwaiterTest();
          Console.ReadLine();
      }
      
      public struct SkipToThreadPoolAwaiter : INotifyCompletion
      {
          public bool IsCompleted => false;
          public int GetResult() 
          {
              Console.WriteLine("調(diào)用GetResult以獲取結(jié)果");
              return 1;
          }
          public void OnCompleted(Action continuation)
          {
              Console.WriteLine("調(diào)用OnCompleted,把Await后面部分要執(zhí)行的代碼傳遞過來(傳遞MoveNext,以推動(dòng)狀態(tài)機(jī)流轉(zhuǎn))");
              ThreadPool.QueueUserWorkItem(state =>
              {
                  Console.WriteLine("開始執(zhí)行Await后面部分的代碼");
                  continuation();
                  Console.WriteLine("后面部分的代碼執(zhí)行完畢");
              });
              Console.WriteLine("返回調(diào)用線程");
          }
      
          public SkipToThreadPoolAwaiter GetAwaiter()
          {
              Console.WriteLine("獲得Awaiter");
              return this;
          }
      }
      

      ??輸出如下

      是否是線程池線程?False
      獲得Awaiter
      調(diào)用OnCompleted,把Await后面部分要執(zhí)行的代碼傳遞過來(傳遞MoveNext,以推動(dòng)狀態(tài)機(jī)流轉(zhuǎn))
      返回調(diào)用線程
      開始執(zhí)行Await后面部分的代碼
      調(diào)用GetResult以獲取結(jié)果
      結(jié)果是1
      是否是線程池線程?True
      后面部分的代碼執(zhí)行完畢
      

      ??對(duì)照前面的文章來看,相信你應(yīng)該有所得,能解決你部分的疑惑。前面說到,我們可以控制continuation的執(zhí)行,那如果當(dāng)前線程有同步上下文(SychronizationContext),我們是不是可以放到同步上下文中執(zhí)行?TaskAwaiter是會(huì)這么做的,如果你不想它使用同步上下文,你可以在Task實(shí)例上調(diào)用ConfigureAwait(false),它表面后面部分的代碼將不會(huì)使用同步上下文執(zhí)行。
      ??另外說一下Task.Yield()這個(gè)Awaiter,他的行為是捕捉同步上下文,如果有,則會(huì)放到同步上下文中執(zhí)行,如果沒有,則會(huì)放到線程池中執(zhí)行。在窗體程序中,有時(shí)候你打開一個(gè)模態(tài)對(duì)話框,會(huì)導(dǎo)致主窗體部分的動(dòng)畫沒有反應(yīng),在模態(tài)對(duì)話框關(guān)閉之后,才會(huì)反應(yīng)。原因是模態(tài)對(duì)話框阻塞了主窗體的消息循環(huán),也就是阻塞了主線程,如果想讓動(dòng)畫先完成,然后再打開模態(tài)對(duì)話框,則可以在打開模態(tài)對(duì)話框之前,Await Task.Yield(),這也對(duì)應(yīng)了它的意思,讓渡之意。
      ??后面文章還會(huì)說明同步上下文具體是什么、異步代碼中使用同步代碼會(huì)導(dǎo)致死鎖的本質(zhì)原因、如何實(shí)現(xiàn)類似Task的類,并且怎么與Async/await這套機(jī)制搭配使用等知識(shí)。
      ??覺得有收獲的不妨點(diǎn)個(gè)贊,有支持才有動(dòng)力寫出更好的文章。(.Net深入學(xué)習(xí)交流群(617374043),歡迎加入!)

      posted @ 2022-03-01 11:55  白煙染黑墨  閱讀(7158)  評(píng)論(7)    收藏  舉報(bào)
      主站蜘蛛池模板: 中文字幕成熟丰满人妻| 亚洲精品综合网中文字幕| 色吊a中文字幕一二三区| 国产97人人超碰caoprom| 人人妻人人澡人人爽曰本| 西昌市| 激情综合网激情综合网激情| 国产成人啪精品午夜网站| 高潮潮喷奶水飞溅视频无码| 国产精品一区在线蜜臀| 日本一卡二卡3卡四卡网站精品 | 性色av无码久久一区二区三区| 又湿又紧又大又爽a视频| 国产卡一卡二卡三免费入口| 国产精品人成视频免费播放| 91精品人妻中文字幕色| 国产精品v片在线观看不卡| 国产色视频一区二区三区qq号| 久热这里只国产精品视频| 国产中文字幕精品视频| 国产AV影片麻豆精品传媒| 男同精品视频免费观看网站| 尤物yw193无码点击进入| 人妻少妇精品中文字幕| 熟女人妻视频| 精品无码av无码专区| 18禁一区二区每日更新| 国产精品亚洲二区在线播放| 国产精品一在线观看| 久久97超碰色中文字幕| 天堂a无码a无线孕交| 亚洲欧洲精品成人久久曰| 国产中文字幕日韩精品| 国产中文三级全黄| 国产亚洲一本大道中文在线| 成人午夜视频在线| 亚洲色在线v中文字幕| a∨变态另类天堂无码专区| 亚洲精品一区二区毛豆| 精品人妻一区二区三区四区在线| 最近中文字幕免费手机版|