为什么是Observable.最后当Observable时没有调用.Generate完成



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

根据我在msdn和其他网站上读到的内容,如果可观察的"优雅地或异常地终止"。我正在测试以下代码(在LINQPad中)看看它是如何工作的,但我根本无法启动.Finall()。

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为10s,则可观察序列结束,Task.ContinueWith启动,但不是。Finally().

如果我将Thread.Sleep设为2s,则可观察序列将被取消,Task.ContinueWith将再次启动,但不是。Finally().

为什么不呢?

查看Finally方法的返回类型;应该给你一个提示。就像Concat方法返回一个新的IObservable,并将新的序列连接到它,但不更改原始序列一样,Finally方法返回了一个具有最终操作的新IObservable,但您订阅了原始IObservable。在你的Subscribe电话前打下面的电话,它就会起作用。

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

我同意这是一个奇怪的API选择;我认为Finally更类似于Subscribe而不是Concat。您正在订阅finally"event";奇怪的是,API强制创建一个全新的IObservable,然后订阅它,只为了实现Finally。此外,如果您订阅两次新的IObservable,则您的Finally函数将执行两次。因此,您必须确保其中一个订阅在"finallied"IObservable上,其他订阅都在原始订阅上。这似乎很不寻常。

我想,Finally并不意味着修改可观察的内容,而是修改订阅本身。也就是说,他们通常不希望您创建具有Finally内容(var o = Observable.[...].Finally(...);)的可公开访问的命名可观测对象,而是希望与订阅调用本身(var subscription = o.Finally(...).Subscribe(...);

内联

相关内容

  • 没有找到相关文章

最新更新