2017年9月29日 星期五

C# : 使用多個工作 task 讀取多網站資料

在這篇文章中,我們將會延續上一篇文章,需要同時讀取四個網頁上的資料,不過,在這裡,我們將會使用 C# 提供的 Task 類別來做到這樣需求。這裡是微軟官方對於 TAP 的需求說明:工作式非同步模式 (TAP) 是以 System.Threading.Tasks 命名空間中的 System.Threading.Tasks.Task 和 System.Threading.Tasks.Task<TResult> 類型為基礎,這兩種類別用於表示任意非同步作業。 在新開發非同步專案時建議使用TAP模式。
在這裡的練習中,我們使用了方法 Task.Factory.StartNew 來建立一個工作,這個靜態方法要接受一個 Action 委派方法作為引數,這個委派方法就是要來進行非同步執行的方法。
Task.WhenAll 方法會以非同步方式來等候多個 Task 或 Task 物件完成,因此,與執行緒的開發設計不同,使用工作可以有更多的方法與技巧,可以等候部分或者全部工作完成後,才會繼續進行處理其他程式碼。
這是執行結果
Press any key for continuing...

http://www.msn.com/zh-tw/ 執行緒 ID 5
https://world.taobao.com/ 執行緒 ID 6
https://tw.yahoo.com/ 執行緒 ID 3
https://www.microsoft.com 執行緒 ID 4
https://www.microsoft.com 的內容大小為 1020 bytes
https://world.taobao.com/ 的內容大小為 220949 bytes
https://www.microsoft.com 花費時間為 268.2176 ms
https://world.taobao.com/ 花費時間為 268.6948 ms
http://www.msn.com/zh-tw/ 的內容大小為 46066 bytes
http://www.msn.com/zh-tw/ 花費時間為 273.3024 ms
https://tw.yahoo.com/ 的內容大小為 192192 bytes
https://tw.yahoo.com/ 花費時間為 447.7144 ms
抓取四個網站內容 花費時間為 509.5968 ms
Press any key for continuing...
底下是完整的測試程式碼
class Program
{
    static string[] Urls = new string[]
    {
        "https://www.microsoft.com",
        "https://tw.yahoo.com/",
        "http://www.msn.com/zh-tw/",
        "https://world.taobao.com/"
    };

    static void Main(string[] args)
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        Task t1 = Task.Factory.StartNew(() =>
        {
            GetWebContent(Urls[0]);
        });
        Task t2 = Task.Factory.StartNew(() =>
        {
            GetWebContent(Urls[1]);
        });
        Task t3 = Task.Factory.StartNew(() =>
        {
            GetWebContent(Urls[2]);
        });
        Task t4 = Task.Factory.StartNew(() =>
        {
            GetWebContent(Urls[3]);
        });

        Task.WhenAll(t1, t2, t3, t4).ContinueWith(t =>
        {
            sw.Stop();
            Console.WriteLine($"抓取四個網站內容 花費時間為 {sw.Elapsed.TotalMilliseconds} ms");
            Console.WriteLine($"Press any key for continuing...{Environment.NewLine}");
        });

        //// 這裡是另外一種做法
        //Task.WhenAll(t1, t2, t3, t4).ContinueWith(t =>
        //{
        //}).Wait();
        //sw.Stop();
        //Console.WriteLine($"抓取四個網站內容 花費時間為 {sw.Elapsed.TotalMilliseconds} ms");
        //Console.WriteLine($"Press any key for continuing...{Environment.NewLine}");


        Console.WriteLine($"Press any key for continuing...{Environment.NewLine}");
        Console.ReadKey();
    }

    private static void GetWebContent(object url)
    {
        Console.WriteLine($"{url} 執行緒 ID {Thread.CurrentThread.ManagedThreadId}");

        Stopwatch sw = new Stopwatch();
        sw.Start();
        using (var client = new HttpClient())
        {
            string content = client.GetStringAsync(url.ToString()).Result;
            Console.WriteLine($"{url} 的內容大小為 {content.Length} bytes");
        }
        sw.Stop();
        Console.WriteLine($"{url} 花費時間為 {sw.Elapsed.TotalMilliseconds} ms");
    }
}

沒有留言:

張貼留言