C#線程學習筆記八:async & await入門

来源:https://www.cnblogs.com/atomy/archive/2019/12/14/12038318.html
-Advertisement-
Play Games

一、涉及內容 async & await是C# 5.0引入的,控制台輸出所使用的$符號(拼接字元串)是C# 6.0引入的,其功能類似於string.Format()方法。 二、多線程、非同步、同步之間的聯繫與區別 廚房案例: 比如說你要炒5道菜ABCDE,但是只有兩個爐子可以用,即同時只能炒兩道菜。在 ...


    一、涉及內容

    async & await是C# 5.0引入的,控制台輸出所使用的$符號(拼接字元串)是C# 6.0引入的,其功能類似於string.Format()方法。

    二、多線程、非同步、同步之間的聯繫與區別

    廚房案例:

    比如說你要炒5道菜ABCDE,但是只有兩個爐子可以用,即同時只能炒兩道菜。在這裡,爐子就是線程。

    假如兩個爐子分別同時炒A和B,那剩下的CDE只能等A或B炒完了才能開始。這個等待的過程就是同步,我們稱之為阻塞,即這個時候你只能炒A和B這兩道菜。

    假如你還有一臺咖啡機,在你炒A和B的時候順手把咖啡豆和水放到咖啡機里打開開關,然後你就不用管它了。此時,就是新開了一個線程去煮咖啡,而煮咖啡

是由咖啡機自動完成的並不影響繼續炒菜,所以煮咖啡這個線程是非同步的,我們稱之為非阻塞

    當咖啡機叮的一聲通知你咖啡已經煮好了,你要去把咖啡拿出來加點糖或奶什麼的,這個拿咖啡的動作我們稱之為回調,這個是咖啡機線程完成之後通知你要去

做的動作。

    簡單來說:

    會占用你的時間讓你無法去做其它事情的任務叫做同步任務(炒菜要專註否則會糊鍋)。

    那些不需要占用你的時間的任務叫做非同步任務(咖啡機自己會把咖啡煮好,不需要你一直看著它)。

    下麵代碼演示不使用非同步的情況:

    class Program
    {
        //創建計時器
        private static readonly Stopwatch stopwatch = new Stopwatch();

        static void Main(string[] args)
        {
            #region async & await入門之不使用非同步
            //啟動計時器
            stopwatch.Start();
            //URL地址
            const string url1 = "http://www.cnblogs.com/";
            const string url2 = "http://www.cnblogs.com/atomy/";
            //非同步下載某網站內容,並統計字元的個數。
            var result1 = CountCharacters("url1", url1);
            var result2 = CountCharacters("url2", url2);
            //主要是通過拼接字元串達到耗時操作
            for (var i = 0; i < 3; i++)
            {
                ExtraOperation(i + 1);
            }
            //控制台輸出
            Console.WriteLine($"{url1} 的字元個數:{result1}");
            Console.WriteLine($"{url2} 的字元個數:{result2}");
            Console.WriteLine($"總耗時{stopwatch.ElapsedMilliseconds}ms。");
            Console.Read();
            #endregion
        }

        /// <summary>
        /// 統計字元個數
        /// </summary>
        /// <param name="id"></param>
        /// <param name="address"></param>
        /// <returns></returns>
        private static int CountCharacters(string name, string address)
        {
            var wc = new WebClient();
            Console.WriteLine($"{name}開始調用,歷時{stopwatch.ElapsedMilliseconds}ms,線程id={Thread.CurrentThread.ManagedThreadId}。");

            var result = wc.DownloadString(address);
            Console.WriteLine($"{name}調用完成,歷時{stopwatch.ElapsedMilliseconds}ms,線程id={Thread.CurrentThread.ManagedThreadId}。");

            return result.Length;
        }

        /// <summary>
        /// 額外操作
        /// </summary>
        /// <param name="id"></param>
        private static void ExtraOperation(int id)
        {
            //這裡是通過拼接字元串進行一些相對耗時的操作
            var s = "";
            for (var i = 0; i < 6000; i++)
            {
                s += i;
            }
            Console.WriteLine($"第{id}次ExtraOperation執行完成,歷時:{stopwatch.ElapsedMilliseconds}ms。");
        }
    }
View Code

    運行結果如下:

    下麵代碼演示使用非同步的情況:

    class Program
    {
        //創建計時器
        private static readonly Stopwatch stopwatch = new Stopwatch();

        static void Main(string[] args)
        {
            #region async & await入門之使用非同步
            //啟動計時器
            stopwatch.Start();
            //URL地址
            const string url1 = "http://www.cnblogs.com/";
            const string url2 = "http://www.cnblogs.com/atomy/";
            //非同步下載某網站內容,並統計字元的個數。
            Task<int> t1 = CountCharactersAsync("url1", url1);
            Task<int> t2 = CountCharactersAsync("url2", url2);
            //主要是通過拼接字元串達到耗時操作
            for (var i = 0; i < 3; i++)
            {
                ExtraOperation(i + 1);
            }
            //控制台輸出
            Console.WriteLine($"{url1} 的字元個數:{t1.Result}");
            Console.WriteLine($"{url2} 的字元個數:{t2.Result}");
            Console.WriteLine($"總耗時{stopwatch.ElapsedMilliseconds}ms。");
            Console.Read();
            #endregion
        }

        /// <summary>
        /// 統計字元個數
        /// </summary>
        /// <param name="id"></param>
        /// <param name="address"></param>
        /// <returns></returns>
        private static async Task<int> CountCharactersAsync(string name, string address)
        {
            var wc = new WebClient();
            Console.WriteLine($"{name}開始調用,歷時{stopwatch.ElapsedMilliseconds}ms,線程id={Thread.CurrentThread.ManagedThreadId}。");

            var result =await wc.DownloadStringTaskAsync(address);
            Console.WriteLine($"{name}調用完成,歷時{stopwatch.ElapsedMilliseconds}ms,線程id={Thread.CurrentThread.ManagedThreadId}。");

            return result.Length;
        }

        /// <summary>
        /// 額外操作
        /// </summary>
        /// <param name="id"></param>
        private static void ExtraOperation(int id)
        {
            //這裡是通過拼接字元串進行一些相對耗時的操作
            var s = "";
            for (var i = 0; i < 6000; i++)
            {
                s += i;
            }
            Console.WriteLine($"第{id}次ExtraOperation執行完成,歷時:{stopwatch.ElapsedMilliseconds}ms。");
        }
    }
View Code

    運行結果如下:

    三、async & await 結構

    async & await結構可分成三部分:

    1)調用方法:該方法調用非同步方法,然後在非同步方法執行其任務的時候繼續執行;

    2)非同步方法:該方法非同步執行工作,然後立刻返回到調用方法;

    3)await表達式:用於非同步方法內部,指出需要非同步執行的任務。一個非同步方法可以包含多個await表達式(不存在 await 表達式的話IDE會發出警告)。

    四、非同步方法

    非同步方法:在執行完成前立即返回調用方法,在調用方法繼續執行的過程中完成任務。

    語法分析:

    1)關鍵字:方法頭使用async修飾符。     2)要求:需有await表達式(可多個)方可進行非同步操作,否則視為普通方法進行同步操作。     3)返回類型:只能返回3種類型(void、Task和Task<T>)。Task和Task<T>標識返回的對象會在將來完成工作,表示調用方法和非同步方法可以繼續執行。     4)參數:數量不限,但不能使用out和ref關鍵字。     5)命名約定:方法尾碼名應以Async結尾。

    參考自:

    https://www.cnblogs.com/woxihuadabai/p/8042652.html

    https://www.cnblogs.com/liqingwen/p/5831951.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 做web開發的時候,我們往往會有很多靜態資源,如html、圖片、css等。那如何向前端返回靜態資源呢?以前做過web開發的同學應該知道,我們以前創建的web工程下麵會有一個webapp的目錄,我們只要把靜態資源放在該目錄下就可以直接訪問。但是,基於Spring boot的工程並沒有這個目錄,那我們應 ...
  • 解決方法: 1. javac -encoding UTF-8 .\Test_Sql.java //加上參數指定utf-8 2.改變文件編碼 使用 ANSI編碼。 ...
  • 人生,抬頭就不能看到地面,低頭就不能仰望天空。記住還記住的,忘記該忘記的,改變能改變的,接受不能改變的。何必無理智的苛求?該是你的,躲著躲不過,不是你的,求也求不來。 ...
  • 本文是Spring Cloud專欄的第七篇文章,瞭解前六篇文章內容有助於更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用組件介紹概覽 Spring Cloud第二篇 | 使用並認識Eureka註冊中心 Spring Cloud第三篇 | 搭建高可用Eurek ...
  • 我的使用的是Visual Studio 2019 原因 學習完一部分東西後,我發現了一個更牛b的東西ABP框架。 所以開始學習ABP框架 https://github.com/aspnetboilerplate/aspnetboilerplate 問題來了, 1.怎麼學習? 去官網直接生成項目【ht ...
  • 到底該用多少線程?線程數、CPU核心數、本地計算時間、等待時間的關係 線程數 = CPU核心數 * ( 本地計算時間 + 等待時間 ) / 本地計算時間 下麵是Task.Factory.StartNew和自己寫的TaskHelper.LargeTask.Run對比測試 一、Task.Factory. ...
  • .net core 3.1簡體中文語言包,英文智能提示變成中文!這個是我自己手動用谷歌翻譯翻譯的一批文檔,已經把.net core3.1完全翻譯了 由於是翻譯器翻譯,所以怕翻譯有錯漏,所以沒有去掉英文提示,中文提示在英文提示下麵。有需要的可以聯繫我的QQ11392301, 由於是勞力翻譯的,挺辛苦, ...
  • 定義http post 調用webservice的某個方法 調用實例: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...