C# 为什么不是';看不见,终于被叫来了?
我不明白最后的方法。在这种情况下它不会开火C# 为什么不是';看不见,终于被叫来了?,c#,system.reactive,C#,System.reactive,我不明白最后的方法。在这种情况下它不会开火 [TestMethod] public void FinallyHappensOnError() { bool finallyActionHappened = false; try { Observable .Throw<Unit>(new DivideByZeroException()) .Finally(() => finallyActionHappened
[TestMethod]
public void FinallyHappensOnError()
{
bool finallyActionHappened = false;
try
{
Observable
.Throw<Unit>(new DivideByZeroException())
.Finally(() => finallyActionHappened = true)
.Subscribe();
}
catch
{
}
Assert.IsTrue(finallyActionHappened);
}
[TestMethod]
公共无效最终出现错误()
{
bool finallyActionOccessed=false;
尝试
{
可观察
.Throw(新的DivideByZeroException())
.最后(()=>finallyaActionOccessed=true)
.Subscribe();
}
抓住
{
}
Assert.IsTrue(最终动作发生);
}
这一个使用Do而不是Finally。我不明白为什么它与Do一起工作,但最终不起作用
[TestMethod]
public void CanRecordWhenSequenceFinishes()
{
bool sequenceFinished = false;
try
{
Observable.Throw<Unit>(new DivideByZeroException())
.Do(
onError: ex => { sequenceFinished = true; },
onCompleted: () => sequenceFinished = true,
onNext: _ => { })
.Subscribe();
}
catch
{
}
Assert.IsTrue(sequenceFinished);
}
[TestMethod]
public void CanRecordWhenSequenceFinishes()
{
bool sequenceFinished=false;
尝试
{
Observable.Throw(新的DivideByZeroException())
.做(
onError:ex=>{sequenceFinished=true;},
未完成:()=>sequenceFinished=true,
onNext:u=>{})
.Subscribe();
}
抓住
{
}
Assert.IsTrue(sequenceFinished);
}
您的代码(双向)是竞争条件。竞赛条件用.Do
解决正确的方式,用解决错误的方式。最后
。为什么比如何避免更不相关:
public async Task FinallyHappensOnError()
{
bool finallyActionHappened = false;
try
{
await Observable.Throw<Unit>(new DivideByZeroException())
.Finally(() => finallyActionHappened = true);
}
catch
{
}
Assert.IsTrue(finallyActionHappened);
}
公共异步任务最终出现错误()
{
bool finallyActionOccessed=false;
尝试
{
wait Observable.Throw(新的DivideByZeroException())
.最后(()=>finallyaActionOccessed=true);
}
抓住
{
}
Assert.IsTrue(最终动作发生);
}
或者,如果您不想使用TPL/async/await:
[TestMethod]
public void FinallyHappensOnError()
{
bool finallyActionHappened = false;
try
{
Observable
.Throw<Unit>(new DivideByZeroException())
.Finally(() => finallyActionHappened = true)
.Subscribe(
_ => {},
() => Assert.IsTrue(finallyActionHappened)
);
}
catch
{
}
}
[TestMethod]
公共无效最终出现错误()
{
bool finallyActionOccessed=false;
尝试
{
可观察
.Throw(新的DivideByZeroException())
.最后(()=>finallyaActionOccessed=true)
.订阅(
_ => {},
()=>Assert.IsTrue(最终动作发生)
);
}
抓住
{
}
}
在您的示例中,Finally
操作未被调用的原因是,通过调用不包含onError
处理程序的“裸”.Subscribe()
重载来订阅可观察序列。当onError
处理程序丢失且序列失败时,将在遇到异常的任何线程上同步引发异常。在您的例子中,您是“幸运的”,异常是在当前线程上抛出的,因此您可以使用catch
块捕获它。否则,将无法处理该异常并使进程崩溃。您可以通过如下修改示例来测试此条件:
Observable
.Throw<Unit>(new DivideByZeroException(), ThreadPoolScheduler.Instance)
.Finally(() => finallyActionHappened = true)
.Subscribe();
Thread.Sleep(500); // Give some time to the unhandled exception to emerge
[TestMethod]
public void FinallyHappensOnError()
{
bool finallyActionHappened = false;
Observable
.Throw<Unit>(new DivideByZeroException())
.Finally(() => finallyActionHappened = true)
.Subscribe(value => { }, error => { }, () => { });
Assert.IsTrue(finallyActionHappened);
}
注意空的catch
块是如何不再需要的。异常的吞咽现在由空的onError
处理程序执行
顺便说一句,此测试的断言之所以成功,是因为可观察序列在订阅期间同步完成。在可观察序列寿命较长的一般情况下,断言将失败,因为将在序列完成之前调用Assert.IsTrue
。出于这个原因,我建议在检查断言之前,先同步或异步地等待可观察序列的完成。下面是一个同步等待的示例,这也意味着连接了所有三个处理程序的完整订阅
Observable
.Throw<Unit>(new DivideByZeroException())
.Finally(() => finallyActionHappened = true)
.DefaultIfEmpty().Wait();
可观察
.Throw(新的DivideByZeroException())
.最后(()=>finallyaActionOccessed=true)
.DefaultIfEmpty().Wait();
异常将由
Wait
操作符同步重新启动,因此您可能希望尝试/捕获它,就像在原始测试中一样。我不完全理解。在什么和什么之间赛跑?测试是否在最终发生之前完成?我认为这一切都是同步的,因为没有延迟、线程调度程序等。实际上,第二段代码中的断言甚至没有被命中。我在上面设置了一个断点,但它没有发生。哦,天哪,我很困惑。我上面的原始测试代码失败了。但是如果我测试的第二行是Subject obs=new Subject()
然后我将其更改为订阅(obs)
,这样不仅测试通过,而且测试永远不会进入Catch块;我在那里放了一个断点,它没有被击中。我阅读了Finally语句。Lee Campbell说,这其中有一个异常——订阅中需要一个OneError操作,否则最终无法运行。如果我在最初的测试方法中将存根放入订阅中,那么测试成功。查看更多背景信息