2017年9月29日 星期五

C# : 使用Async 和 Await 讀取多網站資料

最後,讓我們使用 C# 5.0 的 存取修飾詞 Async / 運算子 Await,寫出一個具有非同步的應用程式;我們這裡一樣會需要去網路抓取四個網頁內容。
首先,我們寫個類別,這個類別裡面只有個方法,GetWebContent,這個方法的回傳值為 Task 物件,而且,我們看到了,在這個方法名稱前面,有用到存取修飾詞 Async,如果您在方法或運算式上使用這個修飾詞,則它是指非同步方法。
另外,在這個非同步方法裡面,我們使用 HttpClient 類別實例化出來的物件,讀取網頁資料,我們在這裡使用了 await client.GetStringAsync(url.ToString());,這裡使用到 await 運算子,而 await 運算子會套用至非同步方法中的工作以暫停執行方法,直到等候的工作完成為止,另外,在其中使用 await 的非同步方法必須由 async 關鍵字修改。當然,在這個方法內,我們還是一樣會進行了解當時使用的執行緒 ID 上哪個以及所耗費的時間。
    public class MyClass
    {
        public async Task GetWebContent(string url)
        {
            Console.WriteLine($"{url} 執行緒 ID {Thread.CurrentThread.ManagedThreadId}");

            Stopwatch sw = new Stopwatch();
            sw.Start();
            using (var client = new HttpClient())
            {
                string content = await client.GetStringAsync(url.ToString());
                Console.WriteLine($"{url} 的內容大小為 {content.Length} bytes");
            }
            sw.Stop();
            Console.WriteLine($"{url} 花費時間為 {sw.Elapsed.TotalMilliseconds} ms");
        }
    }
要使用剛剛寫好的類別,則是相當的簡單,我們需要使用 await 運算子來呼叫 GetWebContent 方法,如同 await myClass.GetWebContent(Urls[0]);
  • 我們對於程式進入點函式 Main,使用這樣方式來宣告 async Task Main(string[] args),並且,你的開發環境需要能夠支援 C# 7.1
  • 您可以嘗試將呼叫 myClass.GetWebContent 方法前面的 await 運算子移除,看看會有何結果。
    底下是移除 await 後的執行結果
https://www.microsoft.com 執行緒 ID 1
https://tw.yahoo.com/ 執行緒 ID 1
http://www.msn.com/zh-tw/ 執行緒 ID 1
https://world.taobao.com/ 執行緒 ID 1
抓取四個網站內容 花費時間為 109.2726 ms
Press any key for continuing...

https://www.microsoft.com 的內容大小為 1020 bytes
https://www.microsoft.com 花費時間為 295.5076 ms
https://world.taobao.com/ 的內容大小為 220947 bytes
https://world.taobao.com/ 花費時間為 283.5818 ms
http://www.msn.com/zh-tw/ 的內容大小為 46320 bytes
http://www.msn.com/zh-tw/ 花費時間為 389.8703 ms
https://tw.yahoo.com/ 的內容大小為 201849 bytes
https://tw.yahoo.com/ 花費時間為 635.2415 ms
底下測試用的程式碼
        static async Task Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            MyClass myClass = new MyClass();
            await myClass.GetWebContent(Urls[0]);
            await myClass.GetWebContent(Urls[1]);
            await myClass.GetWebContent(Urls[2]);
            await myClass.GetWebContent(Urls[3]);

            sw.Stop();
            Console.WriteLine($"抓取四個網站內容 花費時間為 {sw.Elapsed.TotalMilliseconds} ms");
            Console.WriteLine($"Press any key for continuing...{Environment.NewLine}");
            Console.ReadKey();
       }
底下是執行結果內容
https://www.microsoft.com 執行緒 ID 1
https://www.microsoft.com 的內容大小為 1020 bytes
https://www.microsoft.com 花費時間為 525.7561 ms
https://tw.yahoo.com/ 執行緒 ID 9
https://tw.yahoo.com/ 的內容大小為 201849 bytes
https://tw.yahoo.com/ 花費時間為 962.6452 ms
http://www.msn.com/zh-tw/ 執行緒 ID 8
http://www.msn.com/zh-tw/ 的內容大小為 46320 bytes
http://www.msn.com/zh-tw/ 花費時間為 168.9015 ms
https://world.taobao.com/ 執行緒 ID 8
https://world.taobao.com/ 的內容大小為 220947 bytes
https://world.taobao.com/ 花費時間為 267.2545 ms
抓取四個網站內容 花費時間為 1947.116 ms
Press any key for continuing...

沒有留言:

張貼留言