2016-11-26 11 views
1

私は最近、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のダウンロードを開始するだろうかと思う?

    +0

    あなたの前提条件をテストするコードを書かないのはなぜですか?私は一般的にいくつかのコンセプトの詳細を理解するために行っています.... –

    +0

    'WhenAny'は、コレクションに提供された完了したタスクの結果を持ちますが、すべてのタスクをキャンセルまたは完了するように設定しません。イメージ操作を実行すると、ループが繰り返され、追加する次のイメージが取得されます。一方、 'WhenAll'は、指定されたタスクが完了したときにのみ完了するタスクを返します。 – ColinM

    +0

    **スロットル**などの機能を含むTPL DataFlowをいつでも使用できます。また、TPLのパイプライン機能は、上記のコードの目的が実現しようとしているものよりも優れていると思われます。 – MickyD

    答えて

    1

    「GetBitmapAsync」を呼び出すと同時に、すべての画像のダウンロードが同時に実行されます。

    ループは、実行されたループを確認してパネルに追加します。この方法で、到着したらすぐに画像を見ることができます。

    タスクが終了すると、他のタスクのステータスには影響しません。

    +0

    これは、タスクはCreatedステータスの場合にのみ実行されるため、タスクは再実行されないためです。他の状態になっても実行されることはありませんが、現在の状況を正しく返しますか? – Benji

    +0

    タスクを作成することはできますが、ほとんどの場合、タスクはすでに実行中のもの、実行中のものを表していますので、そのタスクを使用して再度実行することはできません。同じ操作。 – vtortola

    関連する問題