1. 程式人生 > >MoMaek淺陌

MoMaek淺陌

 涉及 C# 5.0 引入的 async/await,但在控制檯輸出示例時經常會採用 C# 6.0 的 $"" 來拼接字串,相當於string.Format() 方法。

序言

啟動程式之後,系統會在記憶體中建立一個新的程序。程序是構成執行程式資源的集合。在程序內部,有稱為執行緒的核心物件,它代表的是真正的執行程式。系統會在 Main 方法的第一行語句就開始執行緒的執行。

    執行緒:                ①預設情況,一個程序只包含一個執行緒,從程式的開始到執行結束;                ②執行緒可以派生自其它執行緒,所以一個程序可以包含不同狀態的多個執行緒,來執行程式的不同部分;                ③一個程序中的多個執行緒,將共享該程序的資源;                ④系統為處理器執行所規劃的單元是執行緒,而非程序。

為什麼要使用非同步程式設計

提高程式的效能,相應多端請求或者提高響應速度,採用非同步程式設計。在非同步的程式中,程式碼不需要按照編寫是的順序執行。需要用到5.0引入的 async/await 來構建非同步方法。

不用非同步和使用非同步的比較

未使用非同步執行結果 使用非同步執行結果

技巧類提示: 直接拼接字串是一種比較消耗效能的手段,如果對字串連線有效能要求的話應該使用StringBuilder方法。

程式碼解釋

OldTest.async.await程式碼:

 private static readonly Stopwatch stopwatch = new Stopwatch();

        static void Main(string[] args)
        {
            stopwatch.Start();

            const string strTest1 = "https://www.csdn.net/";
            const string strTest2 = "https://blog.csdn.net/qq_36981814";

            var strCountResult1 = CountChars(1, strTest1);
            var strCountResult2 = CountChars(2, strTest2);

            for (int i = 0; i < 3; i++)
            {
                ExtraOperation(i + 1);
            }

            Debug.WriteLine($"{strTest1} 的字元個數:{strCountResult1}");
            Debug.WriteLine($"{strTest2} 的字元個數:{strCountResult2}");
        }

        private static void ExtraOperation(int id)
        {
            var s = "";

            for (var i = 0; i < 6000; i++)
            {
                s += i;
            }
            Debug.WriteLine($"id={id}的 ExtraOperation 方法完成:{stopwatch.ElapsedMilliseconds} ms");
        }

        private static int CountChars(int id, string address)
        {
            var wc = new WebClient();
            Debug.WriteLine($"開始呼叫 id = {id}:{stopwatch.ElapsedMilliseconds} ms");
            var result = wc.DownloadString(address);
            Debug.WriteLine($"呼叫完成 id = {id}:{stopwatch.ElapsedMilliseconds} ms");
            return result.Length;
        }

NewTest.async.await程式碼:

   private static readonly Stopwatch stopwatch = new Stopwatch();

        static void Main(string[] args)
        {
            stopwatch.Start();

            const string strTest1 = "https://www.csdn.net/";
            const string strTest2 = "https://blog.csdn.net/qq_36981814";

            Task<int> strCountResult1 = CountCharsAsync(1, strTest1);
            Task<int> strCountResult2 = CountCharsAsync(2, strTest2);

            for (int i = 0; i < 3; i++)
            {
                ExtraOperation(i + 1);
            }

            Debug.WriteLine($"{strTest1} 的字元個數:{strCountResult1.Result}");
            Debug.WriteLine($"{strTest2} 的字元個數:{strCountResult2.Result}");

        }

        private static void ExtraOperation(int id)
        {
            var s = "";

            for (var i = 0; i < 6000; i++)
            {
                s += i;
            }
            Debug.WriteLine($"id={id}的 ExtraOperation 方法完成:{stopwatch.ElapsedMilliseconds} ms");
        }

        private static async Task<int> CountCharsAsync(int id, string address)
        {
            var wc = new WebClient();
            Debug.WriteLine($"開始呼叫 id = {id}:{stopwatch.ElapsedMilliseconds} ms");
            var result = await wc.DownloadDataTaskAsync(address);
            Debug.WriteLine($"呼叫完成 id = {id}:{stopwatch.ElapsedMilliseconds} ms");
            return result.Length;
        }

①從 Main 方法執行到 CountCharactersAsync(1, url1) 方法時,該方法會立即返回,然後才會呼叫它內部的方法開始下載內容。該方法返回的是一個 Task<int> 型別的佔位符物件,表示計劃進行的工作。這個佔位符最終會返回 int 型別的值。 ②這樣就可以不必等 CountCharactersAsync(1, url1) 方法執行完成就可以繼續進行下一步操作。到執行 CountCharactersAsync(2, url2)  方法時,跟 ① 一樣返回 Task<int> 物件。 ③然後,Main 方法繼續執行三次 ExtraOperation 方法,同時兩次 CountCharactersAsync 方法依然在持續工作 。 ④t1.Result 和 t2.Result 是指從 CountCharactersAsync 方法呼叫的 Task<int> 物件取結果,如果還沒有結果的話,將阻塞,直有結果返回為止。

 asynic/await結構

 同步方法:一個程式呼叫某個方法,等到其執行完成之後才進行下一步操作。這也是預設的形式。  非同步方法:一個程式呼叫某個方法,在處理完成之前就返回該方法。通過 async/await 我們就可以實現這種型別的方法。  async/await 結構可分成三部分: (1)呼叫方法:該方法呼叫非同步方法,然後在非同步方法執行其任務的時候繼續執行; (2)非同步方法:該方法非同步執行工作,然後立刻返回到呼叫方法; (3)await 表示式:用於非同步方法內部,指出需要非同步執行的任務。一個非同步方法可以包含多個 await 表示式(不存在 await 表示式的話 IDE 會發出警告)。

非同步方法詳解

非同步方法:在執行完成前立即返回呼叫方法,在呼叫方法繼續執行的過程中完成任務。 語法分析: (1)關鍵字:方法頭使用 async 修飾。 (2)要求:包含 N(N>0) 個 await 表示式(不存在 await 表示式的話 IDE 會發出警告),表示需要非同步執行的任務。 (3)返回型別:只能返回 3 種類型(void、Task 和 Task<T>)。Task 和 Task<T> 標識返回的物件會在將來完成工作,表示呼叫方法和非同步方法可以繼續執行。 (4)引數:數量不限,但不能使用 out 和 ref 關鍵字。 (5)命名約定:方法字尾名應以 Async 結尾。 (6)其它:匿名方法和 Lambda 表示式也可以作為非同步物件;async 是一個上下文關鍵字;關鍵字 async 必須在返回型別前。

非同步方法簡單結構圖