2017-11-04 9 views
-1

2番目のコードブロックでアクションブロックの完了を待っているときに、最初のコードブロックがなぜスローされるのか説明できますか?データフローブロックの連鎖はないので、伝播は必要ありません。Actionブロックの例外処理を理解する

ActionBlock定義1:

ActionBlock<int> workerBlock = new ActionBlock<int>(async (i) => 
{ 
    await Task.Delay(1); 
    throw new OperationCanceledException(); 
}); 

ActionBlock定義2:

ActionBlock<int> workerBlock = new ActionBlock<int>(async (i) => 
{ 
    await ExceptionThrower1(); 
}); 


private static async Task ExceptionThrower1() 
{ 
    CancellationTokenSource source= new CancellationTokenSource(); 
    source.CancelAfter(100); 
    await ExceptionThrower2(source.Token); 
} 

private static async Task ExceptionThrower2(CancellationToken token) 
{ 
    await Task.Delay(1000); 
    try 
    { 
     token.ThrowIfCancellationRequested(); 
    } 
    catch (OperationCanceledException e) 
    { 
     Console.WriteLine(e); 
     throw; 
    } 
} 

テストプログラム:私は最初の定義を使用する場合は、 "完了"

workerBlock.SendAsync(1).GetAwaiter().GetResult(); 
workerBlock.SendAsync(1).GetAwaiter().GetResult(); 
workerBlock.SendAsync(1).GetAwaiter().GetResult(); 

workerBlock.Complete(); 
workerBlock.Completion.GetAwaiter().GetResult(); 
Console.WriteLine("Done"); 

取得していません完了を待って例外がスローされるため、印刷されます。 2番目の定義では、「完了」が表示されますが、ExceptionThrower2で例外が表示されていることがわかります。

このblogpostに基づいて - https://blogs.msdn.microsoft.com/pfxteam/2011/11/09/exception-handling-in-tpl-dataflow-networks/でも、2番目のものは考慮され、処理されない例外であり、完了時にスローされるべきですか?

答えて

0

私の場合、「完了」は毎回印刷されていましたが、あなたが説明した振る舞いを再現することができませんでした。ただし、OperationCanceledExceptionは、「Cooperative Cancellationを示す例外」カテゴリの下にあり、Exception Handling (Task Parallel Library)を参照し、OperationCanceledExceptionを検索します。

+0

ええ、そうです。私はこの間、最初のスニペットでちょうど "例外"を使用しようとしていたと思います。 OperationCanceledExceptionは、別の方法で扱われます。 – RLV

0

てみ

ActionBlock<int> workerBlock = new ActionBlock<int>((i) => 
{ 
    ExceptionThrower1().Wait(); 
}); 

ActionBlockがすでに非同期のものを処理します。余分なレイヤーを追加すると、あなたの例外を飲み込むようです。