私は最近、TAPを使用するためのいくつかのドキュメント、特にthis pageの小さな見出し "Task.WhenAny"で読んでいました。インターリーブの下 Task.WhenAll絞り込みの効率
をインターリーブ
- 冗長
- (および間接的にスロットル)項、彼らはこれを持っている:彼らはTask.WhenAny 4つの主な目的を述べますコード
List<Task<Bitmap>> imageTasks = (from imageUrl in urls select GetBitmapAsync(imageUrl)).ToList(); while(imageTasks.Count > 0) { try { Task<Bitmap> imageTask = await Task.WhenAny(imageTasks); imageTasks.Remove(imageTask); Bitmap image = await imageTask; panel.AddImage(image); } catch{} }
このコードはかなり非効率的ではないでしょうか?私は、いったんTask.WhenAllの最初のタスクが完了すると、リストの他のタスクを "RanToCompletion"または "Canceled"または他のタスクの進捗状況を殺す他のステータスに設定することを前提としています。したがって、この例のように画像をダウンロードするタスクが2つしかなくても、1枚の画像が2MBで、もう1枚が4MBだったとしても、2MBの画像が最初に終了する可能性があります(2MBのMBまたはもう1枚の画像が受信されます) 。その後、リストから2MBを削除し、ループを開始します。これは、それはその後、本質的にすでに行われた進歩を無駄に、再び4MBのダウンロードを開始するだろうかと思う?
あなたの前提条件をテストするコードを書かないのはなぜですか?私は一般的にいくつかのコンセプトの詳細を理解するために行っています.... –
'WhenAny'は、コレクションに提供された完了したタスクの結果を持ちますが、すべてのタスクをキャンセルまたは完了するように設定しません。イメージ操作を実行すると、ループが繰り返され、追加する次のイメージが取得されます。一方、 'WhenAll'は、指定されたタスクが完了したときにのみ完了するタスクを返します。 – ColinM
**スロットル**などの機能を含むTPL DataFlowをいつでも使用できます。また、TPLのパイプライン機能は、上記のコードの目的が実現しようとしているものよりも優れていると思われます。 – MickyD