2016-05-17 3 views
1

私は複数の機能を並行して呼び出し、そのタスクにTPLを使用しています。私は私が実行されるすべての機能まで待つので、私はさらにプロセスのためにそれを使用できる同時辞書内のいくつかの結果を返す必要があり、今 リターンresutlに基づくTPLでの複数のタスクのキャンセル

ConcurrentDictionary<string, List<result>> dictionary = new ConcurrentDictionary<string, List<result>>(); 

var tasks = Task.Run(()=> 
{ 
    new Task(()=> {dictionary.TryAdd("First", CallFirstFunction());}); 
    new Task(()=> {dictionary.TryAdd("Second", CallSecondFunction());}); 
    new Task(()=> {dictionary.TryAdd("Third", CallThirdFunction());}); 
    new Task(()=> {dictionary.TryAdd("Fourth", CallFourthFunction());}); 
}); 

を使用していた、しかし、いくつかが結果を返された場合、私はまた、任意のタスクをキャンセルしたいですタスクの順序に関係なく空です。関数が空の結果を返す場合、残りのすべてのタスクを同時にキャンセルする必要があります。私は "CancellationToken"クラスもチェックしましたが、私はタスクでこれを使用する方法とタスクで関数の状態を共有する方法を混同しています。

ご協力いただければ幸いです。 最高のお礼

+1

結果が必要な場合は、それを待たなければなりません。 'Task.WaitAny'をチェックしてください –

+0

なぜこれらのすべてのコールドタスクを作成していますか? 'new Task'の代わりに、' Task.Run'とCancellationTokenを使ってください。または、メインスレッドが完了するまでブロックしたくない場合は、[Parallel.Invoke](https://msdn.microsoft.com/en-us/library/dd783942(v=vs.110).aspx)を使用してください。 'Parallel.Invoke'はキャンセルトークンを受け入れることもできます。 –

+0

@MikeDebelaブロックして待機する必要はありません。' await Task.WhenAll() 'は非同期で待機します –

答えて

0

キャンセルをサポートするには、CancellationTokenSourceを使用する必要があります。結果が空であるので、ときにCancellationTokenSource.Cancel()

async Task DoWorkAsync() 
{ 
    var cts = new CancellationTokenSource(); 
    var ct = cts.Token; 

    var tasks = new List<Task> 
    { 
     Task.Run(() => AddToDictionary("First",() => CallFirstFunction(), cts), ct), 
     Task.Run(() => AddToDictionary("Second",() => CallSecondFunction(), cts), ct), 
     Task.Run(() => AddToDictionary("Third",() => CallThirdFunction(), cts), ct), 
     Task.Run(() => AddToDictionary("Fourth",() => CallFourthFunction(), cts), ct), 
    }; 

    try 
    {   
     await Task.WhenAll(tasks); 
    } 
    catch (OperationCanceledException ex) 
    { 
    } 
} 

private void AddToDictionary(string key, Func<List<int>> method, CancellationTokenSource cts) 
{ 
    if(cts.IsCancellationRequested) 
     return; 

    var result = method.Invoke(); 
    if(!result.Any()); 
     cts.Cancel(); 

    if(!cts.IsCancellationRequested) 
     dictionary.TryAdd(key, result); 
} 

この例では、呼び出し操作(CallFirstFunctionなど)があることを前提として呼び出すことができますあなたがする必要がどのようなhttps://msdn.microsoft.com/en-us/library/mt674886.aspx

があなたの方法にCancellationTokenSourceを渡すことです参照してください。非同期ではありません(タスクまたはタスクを返しません)。そうでない場合は、CancellationTokenもそれらに渡し、キャンセルを確認する必要があります。ct.ThrowIfCancellationRequested

処理をキャンセルすると、処理する必要があるOperationCanceledExceptionが生成されます。

もちろん、いずれかのメソッドがすでに完了してから別のメソッドが空の結果を返す場合、それらの結果はすでに辞書に存在します。他の動作が必要な場合は、この例では、CancellationTokenSourceがタスクとCancellationTokensとの関係について基本的な考え方を示します

関連する問題