最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

聊一聊C# 8.0中的await foreach使用

 更新時(shí)間:2019年06月05日 11:58:52   作者:碼農(nóng)阿宇  
這篇文章主要介紹了聊一聊C# 8.0中的await foreach使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

AsyncStreamsInCShaper8.0

很開心今天能與大家一起聊聊C# 8.0中的新特性-Async Streams,一般人通??吹竭@個(gè)詞表情是這樣.

簡單說,其實(shí)就是C# 8.0中支持await foreach.

或者說,C# 8.0中支持異步返回枚舉類型async Task<IEnumerable<T>>.

好吧,還不懂?Good,這篇文章就是為你寫的,看完這篇文章,你就能明白它的神奇之處了.

為什么寫這篇文章

Async Streams這個(gè)功能已經(jīng)發(fā)布很久了,在去年的Build 2018 The future of C#就有演示,最近VS 2019發(fā)布,在該版本的Release Notes中,我再次看到了這個(gè)新特性,因?yàn)閷Ξ惒骄幊滩惶煜?所以借著這個(gè)機(jī)會,學(xué)習(xí)新特性的同時(shí),把異步編程重溫一遍.

本文內(nèi)容,參考了Bassam Alugili在InfoQ中發(fā)表的Async Streams in C# 8,撰寫本博客前我已聯(lián)系上該作者并得到他支持.

Async / Await

C# 5 引入了 Async/Await,用以提高用戶界面響應(yīng)能力和對 Web 資源的訪問能力。換句話說,異步方法用于執(zhí)行不阻塞線程并返回一個(gè)標(biāo)量結(jié)果的異步操作。

微軟多次嘗試簡化異步操作,因?yàn)?Async/Await 模式易于理解,所以在開發(fā)人員當(dāng)中獲得了良好的認(rèn)可。

詳見The Task asynchronous programming model in C#

常規(guī)示例

要了解問什么需要Async Streams,我們先來看看這樣的一個(gè)示例,求出5以內(nèi)的整數(shù)的和.

static int SumFromOneToCount(int count)
    {
      ConsoleExt.WriteLine("SumFromOneToCount called!");

      var sum = 0;
      for (var i = 0; i <= count; i++)
      {
        sum = sum + i;
      }
      return sum;
    }

調(diào)用方法.

static void Main(string[] args)
    {
      const int count = 5;
      ConsoleExt.WriteLine($"Starting the application with count: {count}!");
      ConsoleExt.WriteLine("Classic sum starting.");
      ConsoleExt.WriteLine($"Classic sum result: {SumFromOneToCount(count)}");
      ConsoleExt.WriteLine("Classic sum completed.");
      ConsoleExt.WriteLine("################################################");
    }

輸出結(jié)果.

可以看到,整個(gè)過程就一個(gè)線程Id為1的線程自上而下執(zhí)行,這是最基礎(chǔ)的做法.

Yield Return

接下來,我們使用yield運(yùn)算符使得這個(gè)方法編程延遲加載,如下所示.

static IEnumerable<int> SumFromOneToCountYield(int count)
    {
      ConsoleExt.WriteLine("SumFromOneToCountYield called!");

      var sum = 0;
      for (var i = 0; i <= count; i++)
      {
        sum = sum + i;

        yield return sum;
      }
    }

主函數(shù)

static void Main(string[] args)
    {
      const int count = 5;
      ConsoleExt.WriteLine("Sum with yield starting.");
      foreach (var i in SumFromOneToCountYield(count))
      {
        ConsoleExt.WriteLine($"Yield sum: {i}");
      }
      ConsoleExt.WriteLine("Sum with yield completed.");

      ConsoleExt.WriteLine("################################################");
      ConsoleExt.WriteLine(Environment.NewLine);
    }

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

正如你在輸出窗口中看到的那樣,結(jié)果被分成幾個(gè)部分返回,而不是作為一個(gè)值返回。以上顯示的累積結(jié)果被稱為惰性枚舉。但是,仍然存在一個(gè)問題,即 sum 方法阻塞了代碼的執(zhí)行。如果你查看線程ID,可以看到所有東西都在主線程1中運(yùn)行,這顯然不完美,繼續(xù)改造.

Async Return

我們試著將async用于SumFromOneToCount方法(沒有yield關(guān)鍵字).

static async Task<int> SumFromOneToCountAsync(int count)
    {
      ConsoleExt.WriteLine("SumFromOneToCountAsync called!");

      var result = await Task.Run(() =>
      {
        var sum = 0;

        for (var i = 0; i <= count; i++)
        {
          sum = sum + i;
        }
        return sum;
      });

      return result;
    }

主函數(shù).

static async Task Main(string[] args)
    {
      const int count = 5;
      ConsoleExt.WriteLine("async example starting.");
      // Sum runs asynchronously! Not enough. We need sum to be async with lazy behavior.
      var result = await SumFromOneToCountAsync(count);
      ConsoleExt.WriteLine("async Result: " + result);
      ConsoleExt.WriteLine("async completed.");

      ConsoleExt.WriteLine("################################################");
      ConsoleExt.WriteLine(Environment.NewLine);
    }

運(yùn)行結(jié)果.

我們可以看到計(jì)算過程是在另一個(gè)線程中運(yùn)行,但結(jié)果仍然是作為一個(gè)值返回!任然不完美.

如果我們想把惰性枚舉(yield return)與異步方法結(jié)合起來,即返回Task<IEnumerable,這怎么實(shí)現(xiàn)呢?

Task<IEnumerable>

我們根據(jù)假設(shè)把代碼改造一遍,使用Task<IEnumerable<T>>來進(jìn)行計(jì)算.

可以看到,直接出現(xiàn)錯(cuò)誤.

IAsyncEnumerable

其實(shí),在C# 8.0中Task<IEnumerable>這種組合稱為IAsyncEnumerable。這個(gè)新功能為我們提供了一種很好的技術(shù)來解決拉異步延遲加載的問題,例如從網(wǎng)站下載數(shù)據(jù)或從文件或數(shù)據(jù)庫中讀取記錄,與 IEnumerable 和 IEnumerator 類似,Async Streams 提供了兩個(gè)新接口 IAsyncEnumerable 和 IAsyncEnumerator,定義如下:

public interface IAsyncEnumerable<out T>
  {
    IAsyncEnumerator<T> GetAsyncEnumerator();
  }

  public interface IAsyncEnumerator<out T> : IAsyncDisposable
  {
    Task<bool> MoveNextAsync();
    T Current { get; }
  }

  // Async Streams Feature 可以被異步銷毀 
  public interface IAsyncDisposable
  {
   Task DiskposeAsync();
  }

AsyncStream

下面,我們就來見識一下AsyncStrema的威力,我們使用IAsyncEnumerable來對函數(shù)進(jìn)行改造,如下.

static async Task ConsumeAsyncSumSeqeunc(IAsyncEnumerable<int> sequence)
    {
      ConsoleExt.WriteLineAsync("ConsumeAsyncSumSeqeunc Called");

      await foreach (var value in sequence)
      {
        ConsoleExt.WriteLineAsync($"Consuming the value: {value}");

        // simulate some delay!
        await Task.Delay(TimeSpan.FromSeconds(1));
      };
    }

    private static async IAsyncEnumerable<int> ProduceAsyncSumSeqeunc(int count)
    {
      ConsoleExt.WriteLineAsync("ProduceAsyncSumSeqeunc Called");
      var sum = 0;

      for (var i = 0; i <= count; i++)
      {
        sum = sum + i;

        // simulate some delay!
        await Task.Delay(TimeSpan.FromSeconds(0.5));

        yield return sum;
      }
    }

主函數(shù).

 static async Task Main(string[] args)
    {
      const int count = 5;
      ConsoleExt.WriteLine("Starting Async Streams Demo!");

      // Start a new task. Used to produce async sequence of data!
      IAsyncEnumerable<int> pullBasedAsyncSequence = ProduceAsyncSumSeqeunc(count);

      // Start another task; Used to consume the async data sequence!
      var consumingTask = Task.Run(() => ConsumeAsyncSumSeqeunc(pullBasedAsyncSequence));

      await Task.Delay(TimeSpan.FromSeconds(3));

      ConsoleExt.WriteLineAsync("X#X#X#X#X#X#X#X#X#X# Doing some other work X#X#X#X#X#X#X#X#X#X#");

      // Just for demo! Wait until the task is finished!
      await consumingTask;

      ConsoleExt.WriteLineAsync("Async Streams Demo Done!");
    }

如果一切順利,那么就能看到這樣的運(yùn)行結(jié)果了.

最后,看到這就是我們想要的結(jié)果,在枚舉的基礎(chǔ)上,進(jìn)行了異步迭代.

可以看到,整個(gè)計(jì)算過程并沒有造成主線程的阻塞,其中,值得重點(diǎn)關(guān)注的是紅色方框區(qū)域的線程5!線程5!線程5!線程5在請求下一個(gè)結(jié)果后,并沒有等待結(jié)果返回,而是去了Main()函數(shù)中做了別的事情,等待請求的結(jié)果返回后,線程5又接著執(zhí)行foreach中任務(wù).

Client/Server的異步拉取

如果還沒有理解Async Streams的好處,那么我借助客戶端 / 服務(wù)器端架構(gòu)是演示這一功能優(yōu)勢的絕佳方法。

同步調(diào)用

客戶端向服務(wù)器端發(fā)送請求,客戶端必須等待(客戶端被阻塞),直到服務(wù)器端做出響應(yīng).

示例中Yield Return就是以這種方式執(zhí)行的,所以整個(gè)過程只有一個(gè)線程即線程1在處理.

異步調(diào)用

客戶端發(fā)出數(shù)據(jù)塊請求,然后繼續(xù)執(zhí)行其他操作。一旦數(shù)據(jù)塊到達(dá),客戶端就處理接收到的數(shù)據(jù)塊并詢問下一個(gè)數(shù)據(jù)塊,依此類推,直到達(dá)到最后一個(gè)數(shù)據(jù)塊為止。這正是 Async Streams 想法的來源。

最后一個(gè)示例就是以這種方式執(zhí)行的,線程5詢問下一個(gè)數(shù)據(jù)后并沒有等待結(jié)果返回,而是去做了Main()函數(shù)中的別的事情,數(shù)據(jù)到達(dá)后,線程5又繼續(xù)處理foreach中的任務(wù).

Tips

如果你使用的是.net core 2.2及以下版本,會遇到這樣的報(bào)錯(cuò).

需要安裝.net core 3.0 preview的SDK(截至至博客撰寫日期4月9日,.net core SDK最新版本為3.0.100-preview3-010431),安裝好SDK后,如果你是VS 2019正式版,可能無法選擇3.0的與預(yù)覽版,聽過只有VS 2019 Preview才支持.Net core 3.0的預(yù)覽版.

總結(jié)

我們已經(jīng)討論過 Async Streams,它是一種出色的異步拉取技術(shù),可用于進(jìn)行生成多個(gè)值的異步計(jì)算。

Async Streams 背后的編程概念是異步拉取模型。我們請求獲取序列的下一個(gè)元素,并最終得到答復(fù)。Async Streams 提供了一種處理異步數(shù)據(jù)源的絕佳方法,希望對大家能夠有所幫助。

文章中涉及的所有代碼已保存在我的GitHub中,請盡情享用!
https://github.com/liuzhenyulive/AsyncStreamsInCShaper8.0

致謝

之前一直感覺國外的大師級開發(fā)者遙不可及甚至高高在上,在遇到Bassam Alugili之后,我才真正感受到技術(shù)交流沒有高低貴賤,正如他對我說的 The most important thing in this world is sharing the knowledge!
 Thank you,I will keep going!!

參考文獻(xiàn): Async Streams in C# 8

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C# StringBuilder和string

    C# StringBuilder和string

    這篇文章主要介紹了C# StringBuilder和string,文章圍繞StringBuilder和string的相關(guān)資料展開內(nèi)容,需要的朋友可以參考一下
    2021-11-11
  • C#中的委托數(shù)據(jù)類型簡介

    C#中的委托數(shù)據(jù)類型簡介

    委托是一個(gè)類型安全的對象,它指向程序中另一個(gè)以后會被調(diào)用的方法(或多個(gè)方法)。通過本文給大家介紹C#中的委托數(shù)據(jù)類型簡介,對c委托類型相關(guān)知識感興趣的朋友一起學(xué)習(xí)吧
    2016-03-03
  • 淺談C#中的Async和Await的用法詳解

    淺談C#中的Async和Await的用法詳解

    這篇文章主要介紹了淺談C#中的Async和Await的用法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 12306奇葩驗(yàn)證碼引發(fā)思考之C#實(shí)現(xiàn)驗(yàn)證碼程序

    12306奇葩驗(yàn)證碼引發(fā)思考之C#實(shí)現(xiàn)驗(yàn)證碼程序

    春運(yùn)最高峰來了!明天通過網(wǎng)絡(luò)將能買到小年夜的車票,本周四就將開售除夕日車票,但不少人被首次在春運(yùn)期間使用的圖片驗(yàn)證碼搞得很火大,小編也正在對驗(yàn)證碼進(jìn)行研究,編寫了由C#實(shí)現(xiàn)驗(yàn)證碼程序,分享給大家
    2015-12-12
  • C#實(shí)現(xiàn)表格數(shù)據(jù)轉(zhuǎn)實(shí)體的示例代碼

    C#實(shí)現(xiàn)表格數(shù)據(jù)轉(zhuǎn)實(shí)體的示例代碼

    在實(shí)際開發(fā)過程中,特別是接口對接之類的,對于這種需求是屢見不鮮,現(xiàn)在很多在線平臺也都提供了像json轉(zhuǎn)實(shí)體、sql轉(zhuǎn)實(shí)體等。本文將用C#實(shí)現(xiàn)這一功能,需要的可以參考一下
    2022-09-09
  • C# FileSystemWatcher 在監(jiān)控文件夾和文件時(shí)的使用方法

    C# FileSystemWatcher 在監(jiān)控文件夾和文件時(shí)的使用方法

    這篇文章主要介紹了C# FileSystemWatcher 在監(jiān)控文件夾和文件時(shí)的使用方法,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以參考下
    2020-06-06
  • C#連接加密的Sqlite數(shù)據(jù)庫的方法

    C#連接加密的Sqlite數(shù)據(jù)庫的方法

    對數(shù)據(jù)加密分兩種,一種是對數(shù)據(jù)庫本身進(jìn)行加密,另一種是對數(shù)據(jù)表中的數(shù)據(jù)進(jìn)行加密,下面通過本文給大家介紹C#連接加密的Sqlite數(shù)據(jù)庫的方法,感興趣的朋友一起看看吧
    2017-08-08
  • C#解析JSON實(shí)例

    C#解析JSON實(shí)例

    這篇文章主要介紹了C#解析JSON的方法,主要采用了C#自帶的JavaScriptSerializer類來實(shí)現(xiàn),方法簡單實(shí)用,需要的朋友可以參考下
    2014-09-09
  • C#實(shí)現(xiàn)順序表(線性表)完整實(shí)例

    C#實(shí)現(xiàn)順序表(線性表)完整實(shí)例

    這篇文章主要介紹了C#實(shí)現(xiàn)順序表(線性表)的方法,結(jié)合完整實(shí)例形式分析了順序表的原理及C#相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-06-06
  • c#定期刪除文件的實(shí)操方法

    c#定期刪除文件的實(shí)操方法

    在本篇文章里小編給大家分享了關(guān)于c#定期刪除文件的方法和步驟,有需要的朋友們可以學(xué)習(xí)下。
    2019-02-02

最新評論

科技| 宿州市| 安多县| 伽师县| 昌邑市| 洛浦县| 肃宁县| 微博| 海盐县| 阳泉市| 静安区| 东城区| 加查县| 岑巩县| 雷山县| 永新县| 交城县| 镇康县| 东平县| 邯郸市| 翁源县| 仙游县| 牡丹江市| 冀州市| 邻水| 大渡口区| 仁寿县| 基隆市| 乐安县| 隆化县| 卫辉市| 安顺市| 富蕴县| 汤原县| 重庆市| 玉龙| 琼结县| 山阳县| 阳曲县| 江安县| 宜章县|