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

          一文看懂: C# 中的異步流

          共 2433字,需瀏覽 5分鐘

           ·

          2022-02-22 16:09

          在閱讀本文前,建議先閱讀本系列的上一篇文章『理解 yield 關(guān)鍵字』。我們知道,使用 C# 的 yield 關(guān)鍵字可以實現(xiàn)一個迭代器(Iterator),使用 async/await 關(guān)鍵字可以實現(xiàn)一個異步方法。異步流(Asynchronous Stream)就是這兩種功能的結(jié)合體,它實現(xiàn)了以異步的方式生成和消費一組數(shù)據(jù)系列的迭代器。

          異步流的支持主要建立在 C# 8 引入的兩個接口上:

          public?interface?IAsyncEnumerable<out?T>
          {
          IAsyncEnumerator GetAsyncEnumerator (...);
          }
          public?interface?IAsyncEnumerator<out?T>: IAsyncDisposable
          {
          T Current { get; }
          ValueTask<bool> MoveNextAsync();
          }

          所以理解了上一篇我們講的 yield 關(guān)鍵字,就很容易理解異步流,它只是在原來的基礎(chǔ)上支持通過 yield return 返回異步得到的一系列結(jié)果值而已。從序列中獲取每個元素的行為(MoveNextAsync)是一個異步操作,元素是以零散的方式到達,這就形成了所謂的“異步流”(比如視頻流中的數(shù)據(jù))。

          這里 IAsyncEnumerator 接口的 ValueTaskTask 類型輕量化的封裝,它是結(jié)構(gòu)類型(值類型)。使用方式與 Task 相似,但它在同步完成任務或返回立即可用的結(jié)果時(這在列舉序列時會經(jīng)常發(fā)生),可以避免不必要的內(nèi)存開銷,比 Task 更高效。

          在上一篇文章中的 Fibonacci 方法中,Thread.Sleep(1000) 用來模擬一個耗時操作,它是“同步”的:

          IEnumerable<int> Fibonacci(int count)
          {
          int prev = 1;
          int curr = 1;
          for (int i = 0; i < count; i++)
          {
          yield?return prev;
          Thread.Sleep(1000);
          int temp = prev + curr;
          prev = curr;
          curr = temp;
          }
          }

          為了提高程序執(zhí)行效率,我們很有可能需要把 Thread.Sleep(1000) 改成“異步”的。如果使它生成異步的數(shù)據(jù)流,該怎么做呢?這就需要同時用到迭代器和異步方法了,也就是說方法中要同時使用 yield returnasync/await 關(guān)鍵字。要支持這一特性,就要使用 IAsyncEnumerable 作為方法的返回類型。于是,前文的 Fibonacci 方法可以這樣改造:

          async IAsyncEnumerable<int> FibonacciAsync(int count)
          {
          int prev = 1;
          int curr = 1;
          Random r = new();
          for (int i = 0; i < count; i++)
          {
          yield?return prev;
          await Task.Delay(1000);
          int temp = prev + curr;
          prev = curr;
          curr = temp;
          }
          }

          不同的是,這個方法允許調(diào)用者以異步的方式消費它生成的數(shù)字系列,換句話說就是使用 await foreach 來遍歷消費這個方法的返回結(jié)果(IAsyncEnumerable),如下所示:

          await?foreach (var n in?FibonacciAsync(10))
          Console.Write("{0} ", n);

          但,如果要在 LINQ 查詢語句中消費異步流,需要先引入 System.Linq.Async NuGet 包,除此之外,使用方式?jīng)]有差別:

          IAsyncEnumerable<int> query =
          from i in?FibonacciAsync(10)
          where i % 2 == 0
          select i * 10;

          await?foreach (var number in query)
          Console.WriteLine(number);

          另外,在 ASP.NET Core 的 Action 方法中也支持返回異步流,如下面示例:

          [HttpGet]
          public?async IAsyncEnumerable<string> Get()
          {
          using?var dbContext = new BookContext();
          await?foreach (var title in dbContext.Books
          .Select(b => b.Title)
          .AsAsyncEnumerable())
          yield?return title;
          }

          綜上,可以看到,異步流解決了零散數(shù)據(jù)系列的異步生成和消費問題。要知道,在 C# 還沒有異步流時,一組數(shù)據(jù)系列(IEnumerable)只能以整體異步的方式(Task>)返回給調(diào)用者。

          參考:

          《C# 9.0 in a nutshell》
          https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/generate-consume-asynchronous-stream


          瀏覽 76
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  亚洲电影91 | 日本黄色影院在线 | AAA在线观看视频 | 日韩黄色视频大全 | 亚洲色婷 |