我需要将RX流(IObservable
)中的错误转换为包含流的订阅的方法中的异常
(由于此问题https://github.com/aspnet/SignalR/pull/1331,Whereby错误未被序列化到客户端。)一旦此问题得到解决,我将恢复正确处理错误
e.g。
我有以下方法
public IObservable<StreamItem> LiveStream()
{
_mySvc.Start();
return _mySvc.ThingChanged();
}
所以我试图订阅流并重新抛出错误,但它仍然没有传输到客户端:
public IObservable<StreamItem> LiveStream()
{
_mySvc.Start();
_mySvc.ThingChanged().Subscribe(item => {}, OnError, () => {});
return _mySvc.ThingChanged();
}
private void OnError(Exception exception)
{
throw new Exception(exception.Message);
}
我需要的是投入LiveStream方法的等效性
e.g。此错误传播给客户
public IObservable<StreamItem> LiveStream()
{
_mySvc.Start();
throw new Exception("some error message");
return _mySvc.ThingChanged();
}
任何想法如何实现这一目标?
答案 0 :(得分:1)
我也发现了这一点,尤其是在“包含”反应性管道的情况下,即具有明确定义的开始和结束的管道。在这种情况下,仅允许基础异常冒泡到包含作用域就足够了。但是,正如您所发现的那样,该概念通常对于Rx而言是陌生的:管道中发生的事情仍留在管道中。
我在一个包含的场景中发现的唯一方法是使用Catch()
将错误“滑出”流,然后递回空的IObservable
以允许流自然地停止(否则,如果您await
要IObservable
完成,则会挂起)。
在您的LiveStream()
方法内 ,这将不起作用,因为该上下文/作用域应该在消耗流之前很久就消失了。因此,这必须在包含整个管道的上下文中发生。
Exception error = null;
var source = LiveStream()
.Catch<WhatYoureStreaming, Exception>(ex => {error = ex; return Observable.Empty<WhatYoureStreaming>(); })
...
await source; // if this is how you're awaiting completion
// not a real exception type, use your own
if (error != null) throw new ContainingException("oops", error);
最后不要throw error
,您将丢失原始堆栈跟踪。
答案 1 :(得分:0)
试试这段代码:
public IObservable<StreamItem> LiveStream()
{
_mySvc.Start();
return
_mySvc
.ThingChanged()
.Materialize()
.Do(x =>
{
if (x.Kind == NotificationKind.OnError)
{
OnError(x.Exception);
}
})
.Dematerialize();
}
我不确定这是最好的方法 - 抛出这样的异常可能会导致你在流中遇到错误的异常处理程序。您可能需要找到另一种解决方案。