C# 可观察。在OnNext启动之前延迟调用Dispose

C# 可观察。在OnNext启动之前延迟调用Dispose,c#,system.reactive,reactive-programming,C#,System.reactive,Reactive Programming,我在理解Observable.Delay如何工作以及何时调用Dispose()时遇到问题。请熟悉Rx的人帮忙好吗 以下代码段: static void Main(string[] args) { var oneNumberEveryFiveSeconds = new SomeObservable(); // Instant echo oneNumberEveryFiveSeconds.SubscribeOn(Scheduler.Th

我在理解Observable.Delay如何工作以及何时调用Dispose()时遇到问题。请熟悉Rx的人帮忙好吗

以下代码段:

    static void Main(string[] args)
    {
        var oneNumberEveryFiveSeconds = new SomeObservable();
        // Instant echo
        oneNumberEveryFiveSeconds.SubscribeOn(Scheduler.ThreadPool).Subscribe(num => Console.WriteLine(num));
        // One second delay
        oneNumberEveryFiveSeconds.Delay(TimeSpan.FromSeconds(1)).SubscribeOn(Scheduler.ThreadPool).Subscribe(num => Console.WriteLine("...{0}...", num));
        // Two second delay
        oneNumberEveryFiveSeconds.Delay(TimeSpan.FromSeconds(2)).SubscribeOn(Scheduler.ThreadPool).Subscribe(num => Console.WriteLine("......{0}......", num));

        Console.ReadKey();
    }

    public class SomeObservable : IObservable<int>
    {
        public IDisposable Subscribe(IObserver<int> o)
        {
            for (var i = 0; i < 2; i++)
            {
                o.OnNext(i);
            }
            o.OnCompleted();

            return new DisposableAction(() => { Console.WriteLine("DISPOSED"); });
        }
    }

    public class DisposableAction : IDisposable
    {
        public DisposableAction(Action dispose)
        {
            this.dispose = dispose;
        }

        readonly Action dispose;

        public void Dispose()
        {
            dispose();
        }
    }
static void Main(字符串[]args)
{
var oneNumberEveryFiveSeconds=newsomeobservable();
//即时回音
oneNumberEveryFiveSeconds.SubscribeOn(Scheduler.ThreadPool.Subscribe(num=>Console.WriteLine(num));
//一秒延迟
oneNumberEveryFiveSeconds.Delay(TimeSpan.FromSeconds(1)).SubscribeOn(Scheduler.ThreadPool).Subscribe(num=>Console.WriteLine(“…{0}…”,num));
//两秒延迟
oneNumberEveryFiveSeconds.Delay(TimeSpan.FromSeconds(2)).SubscribeOn(Scheduler.ThreadPool.Subscribe(num=>Console.WriteLine(“…{0}…”),num));
Console.ReadKey();
}
公共类SomeObservable:IObservable
{
公共IDisposable订阅(IObserver o)
{
对于(变量i=0;i<2;i++)
{
o、 OnNext(i);
}
o、 未完成();
返回新的DisposableAction(()=>{Console.WriteLine(“DISPOSED”);});
}
}
公共类可处置行动:IDisposable
{
公共处置行动(处置行动)
{
dispose=dispose;
}
只读操作处理;
公共空间处置()
{
处置();
}
}
生成以下结果:

0
1
处置
处置
处置
…0…
…1…
……0……
……1……

我希望它更像:

0
1
处置
…0…
…1…
处置
……0……
……1……
处置


任何想法???

如果没有线程池,行为都是相同的:

0 1. 乐意 乐意 ...0... 1. ......0......
……1……

如果我不得不猜测的话,我会说延迟将来自原始可观察对象的项目排成队列,然后根据指定的延迟按其认为合适的方式发送它们。因此,即使原始的可观测对象早已被处理,由延迟方法创建的可观测对象仍然是活跃的。您观察到的行为非常符合此解释。

Rx的标准功能是在序列完成时处理订阅(即使其值仍通过另一个序列传输)


考虑到这一点,
Delay
无法控制从源序列发出值的速度,它只能将值延迟到自己的观察者

如果你去掉“SubscribeOn(Threadpool)”,会发生什么?注意:你的
DisposableAction
是内置的
一次性的。Create
静态方法的副本。嗯,这有点道理,但是为什么延迟的观察对象在开始之前就被处理掉了?据我所知,由Subscribe(onNext)扩展方法创建的IObserver只调用Dispose OnCompleted或OneException。还是我还没有完全理解这一点?这并不是一个延迟观测,而是原始观测。尝试添加()=>Console.WriteLine(“已完成”)以订阅调用。你会看到completed的名字和你期望的一样。我也在另一个论坛(Rx论坛)上发布了这篇文章,得到了很好的解释,谢谢