Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么不是';看不见,终于被叫来了?_C#_System.reactive - Fatal编程技术网

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操作,否则最终无法运行。如果我在最初的测试方法中将存根放入订阅中,那么测试成功。查看更多背景信息