###はじめに
しばらくコードに戸惑った後、例外が必ずしもを介して伝播するとは限らないことを発見しましたContinueWith
。
int zeroOrOne = 1;
Task.Factory.StartNew(() => 3 / zeroOrOne)
.ContinueWith(t => t.Result * 2)
.ContinueWith(t => Console.WriteLine(t.Result))
.ContinueWith(_ => SetBusy(false))
.LogExceptions();
この例では、行が例外のチェーンを「リセット」するため、ゼロ除算の例外は見られず、その後、 「タスクの例外が観察されませんでした...」というメッセージSetBusy
が表示されて爆発します。
だから...私は自分で小さな拡張メソッドを書きました(さまざまなオーバーロードがたくさんありますが、基本的にはすべてこれを行っています):
public static Task ContinueWithEx(this Task task, Action<Task> continuation)
{
return task.ContinueWith(t =>
{
if(t.IsFaulted) throw t.Exception;
continuation(t);
});
}
もう少し調べてみると、このブログ投稿に出くわしました。彼は同様のソリューションを提案していますが、TaskCompletionSource を使用しています。これは (言い換えると) 次のようになります。
public static Task ContinueWithEx(this Task task, Action<Task> continuation)
{
var tcs = new TaskCompletionSource<object>();
task.ContinueWith(t =>
{
if(t.IsFaulted) tcs.TrySetException(t.Exception);
continuation(t);
tcs.TrySetResult(default(object));
});
return tcs.Task;
}
###質問 これら 2 つのバージョンは厳密に同等ですか? それとも、 と の間に微妙な違いがthrow t.Exception
ありtcs.TrySetException(t.Exception)
ますか?
また、これを行った人がインターネット全体で明らかに 1 人しかいないという事実は、私がこれを行う慣用的な方法を見逃していることを示していますか?