我正在使用Rx .NET的Subject.OnError
,它似乎是抛出而不是传播异常。我的情况是,主题是在单独的线程上馈送数据的,返回该数据时,调用线程需要做一些事情,还需要等待可观察对象中的所有数据完成,以及传播发生的任何异常。
这是一个简化的示例:
class Program
{
static async Task Main(string[] args)
{
var subject = new Subject<bool>();
Task.Run(async () =>
{
await Task.Delay(5000);
subject.OnError(new Exception()); //This call is throwing!
});
subject.Subscribe(e =>
{
//Do some data processing here
});
try
{
//Need to wait for observable to complete before returning to the caller
await subject.LastOrDefaultAsync();
}
catch
{
//Do some logging, clean up resources
throw;
}
}
}
如果我删除对subject.Subscribe()
的调用,代码将按您期望的方式工作,并且异常将在subject.LastOrDefaultAsync()
处抛出。但是,在Subscribe
存在的情况下,对subject.OnError()
的调用会立即将异常重新放置到位(而不是将异常传递给可观察到的异常),这对我来说似乎很奇怪。
如何解决此问题?
(仅供参考,已经使用Subject
编写了大量代码,因此建议我完全不使用它是不可接受的解决方案)
答案 0 :(得分:2)
这是一个更简单的示例:
void Main()
{
var subject = new Subject<bool>();
subject.Subscribe(b => {/* bool handling code */});
subject.OnError(new Exception()); //This call is throwing!
}
Subscribe
重载会重新引发它收到的异常。如果要忽略异常,请执行以下操作:
void Main()
{
var subject = new Subject<bool>();
// subject.Subscribe();
subject.Subscribe(b => {/* bool handling code */}, e => { });
subject.OnError(new Exception()); //This call is throwing!
}
如果您想查看此资源,请看这里:https://github.com/dotnet/reactive/blob/master/Rx.NET/Source/src/System.Reactive/Observable.Extensions.cs(第63行)。它会引发任何捕获的异常。
编辑:
如果您想钻进兔子洞,这是(有效的)异常处理代码,该代码最终因.Subscribe(onNextHandlerOnly)
重载而被调用:
void Main()
{
var subject = new Subject<bool>();
subject.Subscribe(b => b.Dump(), e => { e.Throw(); }, () => {});
subject.OnError(new Exception()); //This call is throwing!
}
public static class X
{
public static void Throw(this Exception exception)
{
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(exception).Throw();
}
}
EDI.Capture
调用使它看起来像是异常的“源”是OnError
调用,而不是Subscribe
。