AggregateExceptions で失敗したタスクを待機するときに例外の詳細を保持する
非同期プログラミングには、待機中のタスクが含まれることがよくあります。 ただし、タスクが失敗し、AggregateException
が含まれている場合、標準の await
演算子は最初の例外のみを再スローするため、重要な診断情報が失われる可能性があります。この記事では、AggregateException
.
課題は、AggregateException
の利便性を利用しながら、元の await
を維持することにあります。 try-catch
ブロックで十分だと思われるかもしれませんが、より洗練された有益なソリューションの方が望ましいでしょう。 カスタム awaiter を作成することは可能ですが、不必要な複雑さが追加されます。
問題を示す次の例を考えてみましょう:
<code class="language-csharp">static async Task Run() { Task[] tasks = new[] { CreateTask("ex1"), CreateTask("ex2") }; await Task.WhenAll(tasks); } static Task CreateTask(string message) { return Task.Factory.StartNew(() => { throw new Exception(message); }); }</code>
Run
では、基になるタスクで 2 つの例外が発生しているにもかかわらず、再スローされる例外は 1 つだけです。
このソリューションでは拡張メソッドを利用します:
<code class="language-csharp">public static async Task HandleAggregateExceptions(this Task source) { try { await source.ConfigureAwait(false); } catch (Exception ex) { // Check for null Exception in case of cancellation if (source.Exception == null) throw; // ExceptionDispatchInfo preserves the original exception's stack trace. ExceptionDispatchInfo.Capture(source.Exception).Throw(); } }</code>
この HandleAggregateExceptions
拡張メソッドは、AggregateException
内のすべての例外が適切に再スローされ、元のスタック トレースが保存されることを保証します。これにより、徹底したエラー処理が容易になり、デバッグが簡素化されます。 このメソッドを使用して await tasks.HandleAggregateExceptions();
を呼び出すと、完全な例外の詳細が提供されます。
以上が例外の詳細を失わずにタスクを正確に待機し、AggregateExceptions を処理するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。