Reactive Extensions:将同步订阅转换为异步订阅

时间:2017-04-21 13:13:06

标签: c# asynchronous system.reactive

我对与这段代码类似的一系列可观察数据进行了同步订阅:

integers.Where(id => (id & 1) == 0).Subscribe(id => evenHandler.LRP(id, RandomDelay()));
integers.Where(id => (id & 1) == 1).Subscribe(id => oddHandler.LRP(id, RandomDelay()));

问题是操作是阻塞的,所以你最终会遇到这样的情况:

OddHandler running with ID 1 for 331ms...
EvenHandler running with ID 2 for 651ms...
OddHandler running with ID 3 for 391ms...
EvenHandler running with ID 4 for 633ms...
OddHandler running with ID 5 for 197ms...

我希望操作以异步方式运行,并且我无法访问公开方法IHandler的{​​{1}}接口。经过一些研究后,似乎至少有两种方法可以使用RX来实现这一点:

方法1:

LRP

方法2:

integers.Where(id => (id & 1) == 0)
    .Select(async id => await Task.Run(() => evenHandler.LRP(id, RandomDelay())))
    .Subscribe();

integers.Where(id => (id & 1) == 1)
    .Select(async id => await Task.Run(() => oddHandler.LRP(id, RandomDelay())))
    .Subscribe();

两种方法出现以生成相同的结果。

我的问题:

  1. 这两种技术有什么区别?
  2. 完成我需要做的事情的推荐方法是什么?

1 个答案:

答案 0 :(得分:0)

我会远离方法1 ,因为它会“破坏”Rx。当你在number_of_subs_made@app.route('/status/<int:jobid>') def check_status(jobid): return StatusOfTheWorkBeingCarriedOut(jobid) 进行同步操作时,异步工作。每当你想要异步时,把它放在await里面。 Select甚至直接接受SelectMany

方法2 中,您将SelectMany包装在一个observable中。我相信这与Task<T>非常相似。然而,创建一个Task然后将其转换为可观察对象有点沉重;你可以直接使用一个observable:

Observable.FromAsync()

这将创建一个observable,在内部工作完成时返回Task。我还指定它应该在integers.Where(id => (id & 1) == 0) .SelectMany(id => Observable.Start( () => evenHandler.LRP(id, RandomDelay()), ThreadPoolScheduler.Default)) .Subscribe(); integers.Where(id => (id & 1) == 1) .SelectMany(id => Observable.Start( () => oddHandler.LRP(id, RandomDelay()), ThreadPoolScheduler.Default)) .Subscribe(); 上运行,这使它在Unit内运行。