【问题标题】:Why is Observable.Finally not called when Observable.Generate finishes?为什么 Observable.Finally 在 Observable.Generate 完成时不被调用?
【发布时间】:2013-07-11 04:08:46
【问题描述】:

我需要在两个状态之间交替,每个状态都有不同的间隔时间。
我能想到的最好方法是使用 Reactive Extensions 的 Observable.Generate 这真是太棒了。

根据我在 msdn 和其他网站上阅读的内容,Observable.Finally() 如果 observable “优雅地或异常地终止”。我正在测试以下代码 (在 LINQPad 中)看看它是如何工作的,但我根本无法让 .Final() 触发。

var ia = TimeSpan.FromSeconds(1);
var ib = TimeSpan.FromSeconds(.2);
var start = DateTime.UtcNow;
var ct = new CancellationTokenSource();

var o = Observable.Generate(
    true,
//    s => !ct.IsCancellationRequested,
    s => (DateTime.UtcNow-start) < TimeSpan.FromSeconds(3) && !ct.IsCancellationRequested,
    s => !s,
    s => s ? "on" : "off",
    s => s? ib : ia)
//    .TakeUntil(start+TimeSpan.FromSeconds(3))
    .Concat(Observable.Return("end"));


o.Subscribe( s=> s.Dump(), ct.Token);
var t = o.ToTask(ct.Token);


t.ContinueWith(x => x.Dump("done"));
o.Finally(() => "finallY".Dump()); // never gets called?

Thread.Sleep(10000);
ct.Cancel();

如果我让 Thread.Sleep 10 秒,可观察序列完成并且 Task.ContinueWith 触发, 但不是 .Finally()。

如果我让 Thread.Sleep 2s,可观察序列被取消并且 Task.ContinueWith 再次触发, 但不是 .Finally()。

为什么不呢?

【问题讨论】:

    标签: c# task-parallel-library system.reactive


    【解决方案1】:

    查看Finally方法的返回类型;应该给你一个提示。就像 Concat 方法返回一个 new IObservable 与新的序列连接到它,但不改变原来的,Finally 方法返回一个新的 IObservable 有那个最终行动,但您订阅的是原始的IObservable。将以下行放在您的 Subscribe 调用前面,它会起作用。

    o = o.Finally(() => "finallY".Dump());
    

    我同意这是一个奇怪的 API 选择;我认为Finally 更类似于Subscribe 而不是Concat。您正在订阅最终的“事件”;奇怪的是,API 强制您创建一个全新的IObservable,然后订阅它只是为了让Finally 事情发生。此外,如果您订阅了两次新的IObservable,它可能会出现一个潜在错误(如果我们在您的问题中使用该函数就很明显),您的Finally 函数将执行两次。因此,您必须确保您的订阅之一在“finallied”IObservable 上,而其他订阅都在原始版本上。只是看起来不寻常。

    我想思考的方式是Finally 并不是要修改可观察的,而是要修改订阅本身。即,他们不希望您通常制作具有 Finally 事物 (var o = Observable.[...].Finally(...);) 的可公开访问的命名 observable,而是要与订阅调用本身内联 (var subscription = o.Finally(...).Subscribe(...);)

    【讨论】:

    • 啊,有道理。但是,避免多次调用 finally 的一种方法是不替换为原始 IObservable,而仅将新的用于单个订阅。只需将一行更改为:o.Finally(() =&gt; "finallY".Dump()).Subscribe();
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 2015-12-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-04
    • 2015-09-30
    • 1970-01-01
    相关资源
    最近更新 更多