如果您需要确保流永远不会被异常中断,那么您需要为异常提供另一个通道。
这种行为并非完全出乎意料。从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) => { });
}