解析はenumeratorモードを使って非同期操作を簡略化する詳細解を使う。


まず同期コードを見ます。public int SumPageSizes(IList<Uri>uris){    int total=0    foreach(var uri in uris){        status Text.Text=string.Format(「Found{0}bytes...」、total);        var data=new WebCient().DownloadData(uri);        total+=data.Length;    }     status Text.Text=string.Format(「Found{0}bytes total」、total);    return total;このコードは比較的簡単で、一つずつの同期方式でUri Dataを取得し、統計を行います。非同期方式で統計を一つずつ使うなら、どう計算すればいいですか?以前、醜いコードをデモンストレーションしましたが、大体次の通りです。 WebCient webClient=new WebClient() webClient.DownloadData Completted+=(s,e)=> {      // A対象を使って、何かをする。     WebClient webClient 2=new WebClient()     webClient 2.DownloadData Completted+=(s 2,e 2)=>     {          //Bの相手を使って、何かをします。        // 再帰的にDownloadDataAyncに行きます。     };      webClient 2.DownloadDataAync(new Uri(「Bの住所」); };  webClient.DownloadDataAync(new Uri);もちろん、住所が二つしかないと確定したら、この方法はいいかもしれません。複数の住所があれば再帰的に呼び出さなければなりません。Enumeratorを使って非同期操作を簡略化するにはどうすればいいですか?public void SumPageSizesAsync(IList<Uri>uris){    SumPageSizes AsyncHelper(uris.Get Enumerator(),0);prvate void SumPageSizes AsyncHelper(IEnumerator<Uri>enumerator、int total){    if(enumerator.MoveNext(){        status Text.Text=string.Format(「Found{0}bytes...」、total);        var client=new WebCient()        client.DownloadData Completted+=((sender,e)=>{            SumPageSizes AsyncHelper;        };         client.DownloadDataAync;    }     else{        status Text.Text=string.Format(「Found{0}bytes total」、total);        enumerator.Discpose()    } } SumPageSizes AsyncHelperにより、非同期的にA->非同期的にB->非同期的にCを呼び出すことができます。まず、理由を説明します。urisはA,B,C.SumPageSizes AsyncHelperがあると仮定します。
方法はまずAを呼び出します。Aの後ろにBがありますので、enumerator.MoveNext()はTrueに戻ります。そしてDownloadData Complettedのイベントが終わったら、Bを呼び出します。同様にBの後ろにCがありますので、enumerator.MoveNext()は引き続きTrueに戻ります。Cの呼び出しが完了しました。Cの後ろにはないので、enumerator.MoveNext()はFalseに戻ります。全部ダウンロード済みと考えられます。だから最終結果を返します。
image
 
image asyncとawaitを使って実現すれば、コードは以下の通りです。public async Task<int>SumPageSizes Aync 2(IList<Uri>uris){    int total=0    Char charText='A'    foreach(var uri in uris)    {       var data=await new WebClient().Down loadData Tasky(uri);        total+=data.Length;        Consolie.WriteLine("Thread Id:{0]:呼び出し{1}のアドレスFound{2}bytes…{3}            Thread.Current Thread.ManagedThreadId,charText,total,DateTime.Now);        charText=Covert.ToChar(charText+1)    }    Consolie.WriteLine(「Thread Id:{0]:全部完了しました。Found{1}bytes total{2}        Thread.Current Thread.ManagedThreadId,total,DateTime.Now);    return total;