ストリームが例外によって中断されないようにする必要がある場合は、例外用に別のチャネルが必要です。
この動作は完全に予想外というわけではありません。IObserver<T>
インターフェイスのドキュメントから:
OnError メソッド。通常、データが利用できない、アクセスできない、または破損していること、またはプロバイダーでその他のエラー状態が発生したことを示すために、プロバイダーによって呼び出されます。
これを考えると、ストリームが利用できない、破損しているなどの場合、ストリームを「障害」にする必要があります (これは、WCF で障害が発生しているチャネルに似ています)。IObservable<T>
状態は不確定であるため、実装から得られる他のものに依存することはできません。では、それ以上の観測があることを期待する必要があるのはなぜですか?
とはいえ、いくつかのオプションがあります。
例外を飲み込む
次のように、関数にaction
渡すデリゲートをラップする必要があります。Register
public IDisposable Register<T>(Action<T> action) where T : IMessage
{
return this.subject
.OfType<T>()
.Subscribe(t => {
// Execute action
try { action(t); }
catch { }
});
}
もちろん、これは望ましくないかもしれません。プログラムに影響を与える例外を破棄する可能性があるため (または、ここで何が起こっているかを正確に知っていて、それらをスキップしたい場合もあります)、次のものに基づいて構築するために使用できます。解決。
例外がスローされたときに実行するアクションを提供する
上記をベースとして使用するAction<T, Exception>
と、例外がスローされたときに呼び出される を要求できます。
public IDisposable Register<T>(Action<T> action,
Action<T, Exception> errorHandler) where T : IMessage
{
return this.subject
.OfType<T>()
.Subscribe(t => {
// Execute action
try { action(t); }
catch (Exception e) { errorHandler(t, e); }
});
}
これで、 から例外がスローaction
されると、ストリームを中断することなく例外ハンドラーに渡されます。
上記は簡単にオーバーロードして、例外を飲み込む動作を提供できます(これも、目的に役立つ場合とそうでない場合があります)。
public IDisposable Register<T>(Action<T> action) where T : IMessage
{
// Call the overload, don't do anything on
// exception.
return Register(action, (t, e) => { });
}