ObserveOn 和 Scheduler.NewThread 不会观察到,如果观察者的 OnNext 被阻塞并继续

2024-05-03

有人可以帮助解释为什么当我“阻止并继续”观察者的 onNext 序列订阅具有时间可观察序列的缓冲区时, Scheduler.NewThread 不再适用吗?

例如:

如果我通过缓冲一系列数字

var query = from number in Enumerable.Range(1,200)
            select SnoozeNumberProduction(number);

var observableQuery = query.ToObservable();
var bufferedSequence = observableQuery.Buffer(TimeSpan.FromSeconds(2));

其中 SnoozeNumberProduction 将数字生成延迟 250 毫秒

static int SnoozeNumberProduction(Int32 number)
{
    Thread.Sleep(250);
    return number;
}

现在,如果我使用“ObserveOn(Scheduler.NewThread)”订阅 bufferedSequence,这样我就可以使用 Console.ReadKey 阻止第四个缓冲区

Random random = new Random();
Int32 count = 0;
bufferedSequence.ObserveOn(Scheduler.NewThread).Subscribe(list =>
{
    Console.WriteLine("({0}) Numbers from {1}-{2} produced on Thread ID {3}", list.Count, list[0], list[list.Count -1], Thread.CurrentThread.ManagedThreadId);

    Thread.Sleep(1000);
    count++;
    if (count == 4)
    {
        Console.WriteLine("count reached to 4, blocking ... press any key to continue ");
        Console.ReadKey(); // Block and build up the queue
    }

    Console.WriteLine("Woken " + list[0] + " - " + list[list.Count - 1]);
});

在这种情况下,如果我在 10 秒左右后按任意键,我会看到接下来的几个缓冲区在同一个 ManagedThread 上执行,即使 ObserveOn 中提到了 Scheduler.NewThread。有人可以帮助解释这种行为吗?

示例输出:

(7) Numbers from 1-7 produced on Thread ID 12
Woken 1 - 7
(9) Numbers from 8-16 produced on Thread ID 14
Woken 8 - 16
(8) Numbers from 17-24 produced on Thread ID 15
Woken 17 - 24
(8) Numbers from 25-32 produced on Thread ID 16
count reached to 4, blocking ... press any key to continue
Woken 25 - 32
(8) Numbers from 33-40 produced on Thread ID **16**
Woken 33 - 40
(8) Numbers from 41-48 produced on Thread ID **16**
Woken 41 - 48
(8) Numbers from 49-56 produced on Thread ID **16**
Woken 49 - 56
(8) Numbers from 57-64 produced on Thread ID **16**
Woken 57 - 64
(8) Numbers from 65-72 produced on Thread ID **16**
Woken 65 - 72
(8) Numbers from 73-80 produced on Thread ID **16**
Woken 73 - 80
(8) Numbers from 81-88 produced on Thread ID **16**
Woken 81 - 88
(8) Numbers from 89-96 produced on Thread ID **16**

ObserveOn它本身就是组合序列中的一个层,唯一的工作就是交换到另一个调度程序。然而,你的睡眠发生在Select发生在IEnumerable。然后该序列被转换为IObservable using ToObservable,默认为Dispatcher.CurrentThread.

只有在这一点上,您才会为每个进入的项目交换到另一个线程。如果您将其更改为:

var query = from number in Enumerable.Range(1,200).ToObservable(Dispatcher.NewThread)
            select SnoozeNumberProduction(number);

var bufferedSequence = query.Buffer(TimeSpan.FromSeconds(2));

Now the 枚举发生在一个新线程上,并且由于您没有执行任何操作来更改它,因此它将保留在那里。

其实有一个Observable.Range开始为IObservable并采取可选的IDispatcher。然而,我假设你的来源实际上并不是Enumerable.Range。如果是这样,下面是等价的:

var query = from number in Observable.Range(1,200, Dispatcher.NewThread)
            select SnoozeNumberProduction(number);

var bufferedSequence = query.Buffer(TimeSpan.FromSeconds(2));
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ObserveOn 和 Scheduler.NewThread 不会观察到,如果观察者的 OnNext 被阻塞并继续 的相关文章

随机推荐