キャンセルできる必要がある大規模/長時間実行のワークロードにタスクを使用する場合、タスクが実行するアクションに次のようなテンプレートを使用することがよくあります。
public void DoWork(CancellationToken cancelToken)
{
try
{
//do work
cancelToken.ThrowIfCancellationRequested();
//more work
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception ex)
{
Log.Exception(ex);
throw;
}
}
はOperationCanceledException
エラーとしてログに記録されるべきではありませんが、タスクがキャンセルされた状態に移行する場合は飲み込まないでください。その他の例外は、このメソッドの範囲を超えて処理する必要はありません。
これは常に少し不格好に感じられ、Visual Studioはデフォルトでスローで壊れます(ただし、このパターンを使用しているため、OperationCanceledException
「ユーザー未処理のブレーク」はオフになっています)。OperationCanceledException
更新:それは2021年であり、C#9は私がいつも望んでいた構文を私に与えます:
public void DoWork(CancellationToken cancelToken)
{
try
{
//do work
cancelToken.ThrowIfCancellationRequested();
//more work
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
Log.Exception(ex);
throw;
}
}
public void DoWork(CancellationToken cancelToken)
{
try
{
//do work
cancelToken.ThrowIfCancellationRequested();
//more work
}
catch (Exception ex) exclude (OperationCanceledException)
{
Log.Exception(ex);
throw;
}
}
別の方法は、継続することです。
public void StartWork()
{
Task.Factory.StartNew(() => DoWork(cancellationSource.Token), cancellationSource.Token)
.ContinueWith(t => Log.Exception(t.Exception.InnerException), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously);
}
public void DoWork(CancellationToken cancelToken)
{
//do work
cancelToken.ThrowIfCancellationRequested();
//more work
}
しかし、例外は技術的には複数の内部例外を持つ可能性があり、最初の例のように例外をログに記録する際のコンテキストが少ないため、私はそれが本当に好きではありません(私が単にログに記録する以上のことをしている場合) )。
これはちょっとしたスタイルの問題だと思いますが、誰かもっと良い提案があるかどうか疑問に思っていますか?
例1に固執する必要がありますか?