私の理解では、非同期ボイドは避け、async () =>
はちょうどasync void
です。
これは部分的に間違っています。 async() =>
のいずれかを行うことができ、一致Func<Task>
(良い)またはAction
(悪いです)。良い/悪いの主な理由は、async void
呼び出しで発生する例外がプロセスをクラッシュさせ、一方async Task
例外はキャッチ可能であるということです。
だから我々はちょうどObservable.Finally
ようAction
の代わりにFunc<Task>
にかかるAsyncFinally
オペレータ記述する必要があります。あなたはスワップアウトした場合
try
{
Observable.Interval(TimeSpan.FromMilliseconds(100))
.Take(10)
.AsyncFinally(async() =>
{
await Task.Delay(1000);
throw new NotImplementedException();
})
.Subscribe(i => Console.WriteLine(i));
}
catch(Exception e)
{
Console.WriteLine("Exception caught, no problem");
}
:
public static class X
{
public static IObservable<T> AsyncFinally<T>(this IObservable<T> source, Func<Task> action)
{
return source
.Materialize()
.SelectMany(async n =>
{
switch (n.Kind)
{
case NotificationKind.OnCompleted:
case NotificationKind.OnError:
await action();
return n;
case NotificationKind.OnNext:
return n;
default:
throw new NotImplementedException();
}
})
.Dematerialize()
;
}
}
そして、ここでは、使用のデモだがAsyncFinally
をFinally
にすると、プロセスがクラッシュします。
あなたがここに示されてきた非同期ラムダは '非同期void'方法ですが、すべての非同期ラムダは' void'方法であることを行っているわけではありません。 'Task'が返すメソッドが期待されるコンテキストで非同期ラムダを提供すると、それが得られます。 – Servy