.NET中的Observable:在后台线程上使用'ObserveOn'方法

13

我正在尝试使用 .net 的 Observable 类实现一个简单的观察者模式。我的代码看起来像这样:

Observable.FromEventPattern<PropertyChangedEventArgs>(
    Instance.User,
    "PropertyChanged")
          .Where(e => e.EventArgs.PropertyName == "FirstName")
          .ObserveOn(Scheduler.ThreadPool)
          .Subscribe(search => OnFirstNameChanged(search.EventArgs));

Observable.FromEventPattern<PropertyChangedEventArgs>(
    Instance.User,
    "PropertyChanged")
          .Where(e => e.EventArgs.PropertyName == "LastName")
          .ObserveOn(Scheduler.ThreadPool)
          .Subscribe(search => OnLastNameChanged(search.EventArgs));

我希望观察者在后台线程上运行,但我希望它们都在同一个后台线程上运行(对于我们的实际实现,让每个监听器都在不同的线程上运行会太复杂)。

即,我希望所有的OnXXXChanged逻辑都在UI线程之外的线程上执行,但是我不想在整个线程池上进行Observing,我想确保它们按正确的顺序,在同一个线程上运行。

应该如何修改上述内容?

此外,有没有使用Observable类来实现此模式的好的示例代码?

2个回答

19

你应该创建一个EventLoopScheduler,并在所有对ObserverOn的调用中使用该单个实例:

var scheduler = new EventLoopScheduler(ts => new Thread(ts));

... .ObserveOn(scheduler). ...
工厂方法创建的线程是用于调度执行的线程。将属性 ExitIfEmpty 设置为 false 可以使该线程即使没有任务也不会终止,这意味着它将被重复使用用于每次调用。
但是,您还可以考虑使用 Scheduler.NewThread。使用该调度程序将允许线程在没有更多任务时终止。当通过ObserverOn排队更多工作时,将创建一个新线程,但只应存在单个线程,这意味着您不必同步不同的观察者。
EventLoopScheduler(由 Scheduler.NewThread 使用)创建的线程的名称为 Event Loop #。您将在调试器中看到这些名称。

1
EventLoopScheduler 实现了 IDisposable 接口,所以您需要负责对其进行处理。您可以使用 Using observable 工厂方法将生命周期绑定到订阅。 - Fredrick
Scheduler.NewThread现在已经被弃用,您应该使用NewThreadScheduler.Default代替。 - Kreshnik
1
请注意,在使用上面的答案之前,必须进行轻微修改。例如:var scheduler = new EventLoopScheduler(ts => new Thread(ts) { IsBackground = true }); 必须设置 IsBackground=true。如果没有设置,那么如果该线程仍然活动,它将防止进程退出。 - Contango

6

.ObserveOn(Scheduler.ThreadPool)需要传入一个线程调度器,它决定了观察运行的线程。对于单个线程,您应该使用EventLoopScheduler,而不是ThreadPool。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接