2016-04-14 11 views
2

Taskのコレクションを持っているとすれば、WaitAll()に行く予定です。 すべてが終了する前に、そのコレクションにさらにいくつかのタスクを追加したいとします。まで待つのを待ってから、が完了したとします。終了前にさらに多くのタスクを追加することがあります。既存のWaitAllにさらにタスクを追加

TPLを使用してこれを行うことはできますか?あるいは私自身のスレッド管理をハンドリングする必要がありますか? Task[]上(不潔!)

WaitAll()行為待ちが追加された新しいタスクについて知らないので、私はちょうど、私が上.ToArray()を呼び出すList<Task>を持つことができませんか?

類似した質問WaitAny()については、適用されます。ここで

答えて

1

WaitAllのための1つの解決策は以下のとおりです。

を使用すると、タスクを保持するために、次のリストを持っていると仮定します。ここでは

List<Task> tasks = new List<Task>(); 

は、あなたがそれらを待つことができる方法である。

while (true) 
{ 
    Task[] my_tasks; 

    lock (tasks) 
    { 
     my_tasks = tasks.ToArray(); //take snapshot 
     tasks.Clear(); //clear list 
    } 

    if (my_tasks.Length == 0) 
     break; 

    Task.WaitAll(my_tasks); 
} 

次のようにリストにタスクを追加すると、リストにロックされていることを確認してください:

lock (tasks) 
{ 
    tasks.Add(... 
} 

ところで、非同期的にではなくタスクを同期的に待っている理由はありますか(WaitAllであり、WhenAllではありません)。

+0

Re Wait/Whenは、巨大なレガシーコードベース( 'QueueUserWorkItem' +' ManualResetEvent'ベースのセマフォを置き換える)の中心にあるスレッドをアップグレードし、非同期および/またはコールバックを持っているため、残りのコードベースは許されません。 – Brondahl

0

同期して何かを待ってから、後で別のものを待つ場合は、元の待機をキャンセルして新しいものを開始する必要があります。最初に持っていたものを元の状態で待ってから、さらにタスクを追加する必要がある場合は、現在のタスクリストに追加し、待機を再開するキャンセルを知らせます。もちろん

public class MutableTaskWaiter 
{ 
    private List<Task> _tasks = new List<Task>(); 
    private CancellationTokenSource _cts; 

    public IEnumerable<Task> Tasks 
    { 
     get 
     { 
      lock (_tasks) 
      { 
       return _tasks.ToArray(); 
      } 
     } 
    } 

    public void WaitAll(IEnumerable<Task> tasks) 
    { 
     WaitMoreTasks(tasks); 

     do 
     { 
      try 
      { 
       _cts = new CancellationTokenSource(); 
       Task.WaitAll(_tasks.ToArray(), _cts.Token); 
      } 
      catch (OperationCanceledException) 
      { 
       // start over and wait for new tasks 
      } 
     } 
     while (_cts.IsCancellationRequested); 
    } 


    public void WaitAny(IEnumerable<Task> tasks) 
    { 
     WaitMoreTasks(tasks); 

     do 
     { 
      try 
      { 
       _cts = new CancellationTokenSource(); 
       Task.WaitAny(_tasks.ToArray(), _cts.Token); 
      } 
      catch (OperationCanceledException) 
      { 
       // start over and wait for new tasks 
      } 
     } 
     while (_cts.IsCancellationRequested); 
    } 


    public void WaitMoreTasks(IEnumerable<Task> tasks) 
    { 
     lock (_tasks) 
     { 
      _tasks.AddRange(tasks); 
      if (_cts != null) 
      { 
       // signal the wait to restart with the updated task list 
       _cts.Cancel(); 
      } 
     } 
    } 
} 

あなたはまだあなたが長い時間のためのタスクを追加していて、もともといくつかの短命なタスクを持っている場合思い付くscenarithat WaitAllでの競合条件に対処する必要があるとしています。例えば私のintialタスクリストが5秒後に完了したら、私はすでに待っているので、10秒後に待ちリストに新しいタスクを追加することはできません。

関連する問題