国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

async and await 的入門基礎操作

2020-01-24 03:21:12
字體:
來源:轉載
供稿:網友

如果有幾個Uri,需要獲取這些Uri的所有內容的長度之和,你會如何做?

很簡單,使用WebClient一個一個的獲取uri的內容長度,進行累加。

也就是說如果有5個Uri,請求的時間分別是:1s 2s 3s 4s 5s.

那么需要的時間是:1+2+3+4+5=(6*5)/2=15.

如果采用并行計算的話,結果可能是這樣:

image

總時間長度是5s.

為了演示效果,需要下面3個頁面:

image

其中SlowPage 的Page_load代碼如下:

復制代碼 代碼如下:

protected void Page_Load(object sender, EventArgs e)
{
    Thread.Sleep(5000);
}

VerySlowPage的Page_load事件則 Thread.Sleep(10000);

新建控制臺程序CAStudy:
首先新建類AsyncDemo:
同步的獲取Uris的內容長度代碼如下:
復制代碼 代碼如下:

public class AsyncDemo
    {
        public int SumPageSizes(IList<Uri> uris)
        {
            int total = 0;
            foreach (var uri in uris)
            {
                Console.WriteLine("Thread {0}:Found {1} bytes...{2}",
                    Thread.CurrentThread.ManagedThreadId, total,DateTime.Now);
                var data = new WebClient().DownloadData(uri);
                total += data.Length;
            }
            Console.WriteLine("{0}:Found {1} bytes total {2}",
                Thread.CurrentThread.ManagedThreadId, total, DateTime.Now);
            return total;
        }
    }

在這里SumPageSizes 方法,通過foreach循環一個一個的下載數據。

Main函數如下:
復制代碼 代碼如下:

public static void Main()
{
    List<Uri> uris = new List<Uri>();

    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/QuickPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/SlowPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/VerySlowPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/QuickPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/SlowPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/VerySlowPage.aspx"));
    AsyncDemo asyncDemo = new AsyncDemo();
    int totalSize = asyncDemo.SumPageSizes(uris);
}

Main 函數主要是構造Uri,然后調用AsyncDemo的SumPageSizes方法來獲取所有Uri的內容的總長度。

結果如下:

image 

可以看到時間分別是0s,5s,10s,0s ,5s,10s.所以總長度是(0+5+10)*2=30.

可以看到速度很慢,如果有一個網頁卡住的話,后面很恐怖的哦

下面演示使用async,await的方式:

第一步:將 VS2010 升級到 VS2010 sp1.

第二步:下載Async CTP,進行安裝

第三步:為應用程序添加AsyncCTPLibrary引用,如下:

image 

OK,將上面的SumPageSizes 方法修改如下:

復制代碼 代碼如下:

public async Task<int> SumPageSizesAsync2(IList<Uri> uris)
{
    var tasks = uris.Select(uri => new WebClient().DownloadDataTaskAsync(uri));
    var data = await TaskEx.WhenAll(tasks);
    return await TaskEx.Run(() =>
    {
        return data.Sum(s => s.Length);
    });
}

在AsyncCTPLibrary.dll中,微軟為一些類提供了擴展,如下:

image 

WebClient的擴展如下:

image

可以看到基本上為每個Download 都增加了一個XXXTaskAsync 的擴展方法。

返回的全部都是Task,

為什么全部都是Task?,因為await 只能wait Task,并且await 只能用在async 標記的方法中,

async 關鍵字表明這是個異步方法。

第一句:

public async Task<int> SumPageSizesAsync(IList<Uri> uris)

因為我們申明的是一個異步方法,所以要使用async 關鍵字,SumPageSizesAsync方法返回的結果是int類型,所以返回Task<int>.


第二句:

IEnumerable<Task<Byte[]>> tasks = uris.Select(uri => new WebClient().DownloadDataTaskAsync(uri));

獲取DownloadDataTaskAsync返回的所有Task。

第三句:

byte[][] data = await TaskEx.WhenAll(tasks);

首先第二句返回的是IEnumerable<Task<Byte[]>> 類型,也就是一個一個的Task<Byte[]> 的任務,使用TaskEx的WhenAll方法可以將這些任務轉變成一個Task<Byte[][]> 的任務


使用await關鍵字意味著Task<Byte[][]> 方法需要等待,等待結束后返回Byte[][]。

第四句:

return await TaskEx.Run<int>(() =>

            {

                return data.Sum(s => s.Length);

            });

TaskEx.Run 返回將使用第三句返回的data,將Byte[][] 的數據進行Sum運算,返回一個Task<int> 的對象,如果不使用await 的話:

image

因為 async 關鍵字代表的是異步方法,并且該異步方法返回的結果是int,所以需要再次使用await 關鍵字:

return await TaskEx.Run<int>(() =>
            {
                return data.Sum(s => s.Length);
            });

修改Main代碼如下:

復制代碼 代碼如下:

public static void Main()
{
    List<Uri> uris = new List<Uri>();

    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/QuickPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/SlowPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/VerySlowPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/QuickPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/SlowPage.aspx"));
    uris.Add(new Uri("http://localhost:57815/AsyncTestPages/VerySlowPage.aspx"));
    AsyncDemo asyncDemo = new AsyncDemo();
    Console.WriteLine(DateTime.Now);
    int totalSize = asyncDemo.SumPageSizesAsync(uris).Result;
    Console.WriteLine("TotalSize:{0}, Finished", totalSize);
    Console.WriteLine(DateTime.Now);
}


運行結果如下:

image 

可以看到使用了16秒的時間,大致等于理論值15.

有的同學會說,很麻煩!,的確,我也感覺很麻煩,還不如ThreadPool 來的快,不過async,await主要并不是解決這類問題的,它所解決的是異步中的同步,也就是說在某些異步操作中,需要同步的去處理,比如在Silverlight中,

異步獲取A

主站蜘蛛池模板: 健康| 洛阳市| 安塞县| 东乡| 宣威市| 城市| 肃宁县| 专栏| 永安市| 新余市| 丰城市| 绵竹市| 富宁县| 新丰县| 梓潼县| 肥乡县| 中山市| 高邑县| 凤冈县| 环江| 旌德县| 扶绥县| 杭锦旗| 静安区| 太康县| 洛南县| 金平| 名山县| 马鞍山市| 扎赉特旗| 瑞昌市| 开阳县| 营口市| 昌吉市| 印江| 新化县| 堆龙德庆县| 陆丰市| 陆良县| 南昌市| 信丰县|