使用ReactiveExtensions并行处理集合的值

时间:2013-10-23 22:18:00

标签: c# multithreading system.reactive

我是Rx的新手。根据文档,看起来可以在不同的线程上并行地为每个值运行OnNext处理程序。我只需要ObserveOn适当的调度程序实现。

但是这个简单的代码同步运行:

var dict = new Dictionary<int, object> {{1, null}, {5, null}, {6, null}};

dict.ToObservable()
  .SubscribeOn(ThreadPoolScheduler.Default)
  .Subscribe(kv => {
     Console.WriteLine("Thread {0}, key {1}", Thread.CurrentThread.ManagedThreadId, kv.Key);
     Thread.Sleep(1000);
  });

在屏幕上,我看到每次迭代都有相同的线程ID。我在这里缺少什么?

1 个答案:

答案 0 :(得分:3)

Rx定义了一种语法,它特别禁止OnNext从任何给定的Observer 的角度重叠。有可能并行调用流的多个订阅者(但这取决于Rx运算符的实现者)。

这里我们有两个订阅者以相同流的不同速率处理OnNext:

void Main()
{
    var stream = Observable.Interval(TimeSpan.FromSeconds(1));    

    var sub1 = stream.Subscribe(x => {
        Console.WriteLine("Sub1 handler start: " + Thread.CurrentThread.ManagedThreadId);
        Thread.Sleep(4000);
        Console.WriteLine("Sub1 handler end");
    });

    var sub2 = stream.Subscribe(x => {
        Console.WriteLine("Sub2 handler start: " + Thread.CurrentThread.ManagedThreadId);
        Thread.Sleep(2000);
        Console.WriteLine("Sub2 handler end");
    });

    Console.ReadLine();
}

这是输出,看看Sub2如何在Sub1之前比赛,每个都在他们自己的线程上。

Sub2 handler start: 18
Sub1 handler start: 12
Sub2 handler end
Sub2 handler start: 18
Sub2 handler end
Sub2 handler start: 18
Sub1 handler end
Sub1 handler start: 12
Sub2 handler end
Sub2 handler start: 18
Sub2 handler end
Sub1 handler end
Sub2 handler start: 18
Sub1 handler start: 12

请注意,没有什么可以说每个订阅都是它自己的线程 - 这取决于调度程序和运算符的实现方式。只要它们符合 OnNext *(OnError | OnCompleted)的Rx语法,任何事情都会发生。

对于您的特定情况,我会调查PLINQ / TPL - 它感觉比Rx更合适。

顺便说一下,如果你刚刚开始,李坎贝尔的www.introtorx.com是一个很好的资源。