<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          .NET異步和多線程系列(六)- async/await

          共 5298字,需瀏覽 11分鐘

           ·

          2020-09-12 19:50

          本文是.NET異步和多線程系列的第六章,本章主要對(duì)之前介紹過(guò)的async/await做一些補(bǔ)充說(shuō)明。

          下面我們直接來(lái)看下代碼和運(yùn)行結(jié)果:

          using System;
          using System.Threading;
          using System.Threading.Tasks;

          namespace MyAsyncAwait
          {
          ///
          /// await/async 是C#保留關(guān)鍵字,通常是成對(duì)出現(xiàn),語(yǔ)法糖。
          ///
          /// 主線程調(diào)用async/await方法,主線程遇到await返回執(zhí)行后續(xù)動(dòng)作,
          /// await后面的代碼會(huì)等著Task任務(wù)的完成后再繼續(xù)執(zhí)行
          /// 其實(shí)就像把a(bǔ)wait后面的代碼包裝成一個(gè)ContinueWith的回調(diào)動(dòng)作
          /// 然后這個(gè)回調(diào)動(dòng)作可能是Task線程,也可能是新的子線程,也可能是主線程
          ///
          /// 一個(gè)async方法,如果沒(méi)有返回值,可以方法聲明返回Task
          /// await/async能夠用同步的方式編寫(xiě)代碼,但又是非阻塞的。
          ///
          /// async方法在編譯后會(huì)生成一個(gè)狀態(tài)機(jī)(實(shí)現(xiàn)了IAsyncStateMachine接口)
          ///

          class Program
          {
          static void Main(string[] args)
          {
          Console.WriteLine($
          "當(dāng)前主線程開(kāi)始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
          AwaitAsyncClass.TestShow();
          Console.WriteLine($
          "當(dāng)前主線程結(jié)束 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
          Console.ReadKey();
          }
          }

          ///
          /// await/async關(guān)鍵字 語(yǔ)法糖
          /// await/async 要么不用 要么用到底
          ///

          public class AwaitAsyncClass
          {
          public static void TestShow()
          {
          Test();
          }

          private async static Task Test()
          {
          Console.WriteLine($
          "Test開(kāi)始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");

          Task
          <long> t = SumAsync();
          Console.WriteLine($
          "遇到await主線程回來(lái)干活了 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");

          {
          long lResult = await t; //await后面的代碼會(huì)由線程池的線程執(zhí)行,非阻塞。
          Console.WriteLine($"最終得到的lResult={lResult}");
          }

          {
          //t.Wait(); //主線程等待Task的完成,阻塞的
          //long lResult = t.Result; //訪問(wèn)Result,主線程等待Task的完成,阻塞的,效果跟t.Wait()一樣
          //Console.WriteLine($"最終得到的lResult={lResult}");
          }

          Console.WriteLine($
          "Test結(jié)束 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
          }

          ///
          /// 帶返回值的Task
          /// 要使用返回值就一定要等子線程計(jì)算完畢
          ///

          private static async Task<long> SumAsync()
          {
          Console.WriteLine($
          "SumAsync start ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
          long result = 0;

          //await后面的代碼會(huì)等著Task任務(wù)的完成后再繼續(xù)執(zhí)行
          //其實(shí)就像把a(bǔ)wait后面的代碼包裝成一個(gè)ContinueWith的回調(diào)動(dòng)作
          //然后這個(gè)回調(diào)動(dòng)作可能是Task線程,也可能是新的子線程,也可能是主線程
          await Task.Run(() =>
          {
          for (int k = 0; k < 2; k++)
          {
          Console.WriteLine($
          "SumAsync 第1個(gè) await Task.Run k={k} ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
          Thread.Sleep(
          1000);
          }
          for (long i = 0; i < 999_999_999; i++)
          {
          result
          += i;
          }
          });

          Console.WriteLine($
          "SumAsync 第1個(gè) await Task.Run的后續(xù)任務(wù)開(kāi)始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
          await Task.Run(() =>
          {
          for (int k = 0; k < 2; k++)
          {
          Console.WriteLine($
          "SumAsync 第2個(gè) await Task.Run k={k} ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
          Thread.Sleep(
          1000);
          }
          for (long i = 0; i < 999_999_999; i++)
          {
          result
          += i;
          }
          });

          Console.WriteLine($
          "SumAsync 第2個(gè) await Task.Run的后續(xù)任務(wù)開(kāi)始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
          await Task.Run(() =>
          {
          for (int k = 0; k < 2; k++)
          {
          Console.WriteLine($
          "SumAsync 第3個(gè) await Task.Run k={k} ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
          Thread.Sleep(
          1000);
          }
          for (long i = 0; i < 999_999_999; i++)
          {
          result
          += i;
          }
          });

          Console.WriteLine($
          "SumAsync end ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
          return result;
          }
          }
          }

          運(yùn)行結(jié)果如下:

          仔細(xì)觀察結(jié)果會(huì)發(fā)現(xiàn)

            主線程調(diào)用async/await方法,主線程遇到await后會(huì)返回執(zhí)行后續(xù)動(dòng)作;

            await后面的代碼會(huì)等著Task任務(wù)的完成后再繼續(xù)執(zhí)行,其實(shí)就像把a(bǔ)wait后面的代碼包裝成一個(gè)ContinueWith的回調(diào)動(dòng)作;

            然后這個(gè)回調(diào)動(dòng)作可能是Task線程,也可能是新的子線程,也可能是主線程;

            await/async能夠用同步的方式編寫(xiě)代碼,但又是非阻塞的。

          下面我們調(diào)整下Test方法后再運(yùn)行(紅色的為調(diào)整部分):

          private async static Task Test()
          {
          Console.WriteLine($
          "Test開(kāi)始 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");

          Task
          <long> t = SumAsync();
          Console.WriteLine($
          "遇到await主線程回來(lái)干活了 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");

          {
          //long lResult = await t; //await后面的代碼會(huì)由線程池的線程執(zhí)行,非阻塞。
          //Console.WriteLine($"最終得到的lResult={lResult}");

          }

          {
          //t.Wait(); //主線程等待Task的完成,阻塞的
          long lResult = t.Result; //訪問(wèn)Result,主線程等待Task的完成,阻塞的,效果跟t.Wait()一樣
          Console.WriteLine($"最終得到的lResult={lResult}"
          );
          }

          Console.WriteLine($
          "Test結(jié)束 ManagedThreadId={Thread.CurrentThread.ManagedThreadId}");
          }

          調(diào)整后運(yùn)行結(jié)果如下:

          仔細(xì)觀察結(jié)果會(huì)發(fā)現(xiàn)

            訪問(wèn)Result,主線程會(huì)等待Task的完成,阻塞的。

          其實(shí)async方法在編譯后會(huì)生成一個(gè)狀態(tài)機(jī)(實(shí)現(xiàn)了IAsyncStateMachine接口),有興趣的可以自行去了解下。

          至此本文就介紹完了,有興趣的還可以看下我之前寫(xiě)過(guò)一篇也是關(guān)于async/await的文章:https://www.cnblogs.com/xyh9039/p/11391507.html

          ?

          Demo源碼:

          鏈接:https://pan.baidu.com/s/1jnG5IpteuKCdmF6-tr--cA
          提取碼:3onm

          此文由博主精心撰寫(xiě)轉(zhuǎn)載請(qǐng)保留此原文鏈接:https://www.cnblogs.com/xyh9039/p/13622122.html

          版權(quán)聲明:如有雷同純屬巧合,如有侵權(quán)請(qǐng)及時(shí)聯(lián)系本人修改,謝謝!??!

          版權(quán)申明:本文來(lái)源于網(wǎng)友收集或網(wǎng)友提供,如果有侵權(quán),請(qǐng)轉(zhuǎn)告版主或者留言,本公眾號(hào)立即刪除。


          瀏覽 61
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉伊人18禁止出售借阅 | 爱搞搞就搞搞爱 | 99久久婷婷豆花 | 99看自拍| 草草天天视频 |