次の同期コードを想定します。
try
{
Foo();
Bar();
Fubar();
Console.WriteLine("All done");
}
catch(Exception e) // For illustration purposes only. Catch specific exceptions!
{
Console.WriteLine(e);
}
ここで、これらすべてのメソッドにAsyncの対応物があり、何らかの理由でそれらを使用する必要があると仮定します。したがって、単にすべてを新しいタスクでラップすることはオプションではありません。
どうすれば同じ動作を実現できますか?
「同じ」とは、次のことを意味します。
- 例外がスローされた場合は、例外のハンドラーを実行します。
- 例外がスローされた場合は、次のメソッドの実行を停止します。
私が思いついた唯一のことは恐ろしいことです:
var fooTask = FooAsync();
fooTask.ContinueWith(t => HandleError(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
fooTask.ContinueWith(
t =>
{
var barTask = BarAsync();
barTask.ContinueWith(t => HandleError(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
barTask.ContinueWith(
t =>
{
var fubarTask = FubarAsync();
fubarTask.ContinueWith(t => HandleError(t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
fubarTask.ContinueWith(
t => Console.WriteLine("All done"),
TaskContinuationOptions.OnlyOnRanToCompletion);
},
TaskContinuationOptions.OnlyOnRanToCompletion);
},
TaskContinuationOptions.OnlyOnRanToCompletion);
ご注意ください:
- .NET 4で動作するソリューションが必要なので
async/await
、問題外です。ただし、それがうまくいく場合は、そのasync/await
方法を自由に示してください。 - TPLを使用する必要はありません。TPLで不可能な場合は、別のアプローチで問題ありません。おそらくReactive Extensionsを使用しますか?