将ObserveOn用于Observables的必要性?

时间:2012-01-30 21:25:35

标签: c# c#-4.0 system.reactive

请参阅以下代码:

 var obs = Observable.Start(() => LongRunningMethodToRetrieveData());

 obs.Subscribe(x => MethodThatMustBeOnUIThread(x));

如果我确定在UI线程上执行了这两行代码,是否需要先调用ObserveOn(SynchronizationContext.Current)?或者类似地,我是否需要检查InvokeRequired内的MethodThatMustBeOnUIThread

基本上,我保证使用这两行代码可以在创建订阅的线程上调用'OnNext'吗?

感谢。

编辑:嗯,我在调试器中尝试过并且确实从后台线程调用了'MethodThatMustBeOnUIThread'。为什么是这样?我现在的假设是默认情况下会在运行异步方法的线程上发生观察。

1 个答案:

答案 0 :(得分:1)

您需要熟悉各种Rx方法使用的默认调度程序。

Observable.Generate这样的方法会在订阅observable的线程上运行。

另一方面,Observable.Start方法的目的是在订阅observable时异步调用lamdba操作。如果它发生在UI线程上,它将不是异步的。因此,在这种情况下,它使用ThreadPool调度程序。

这可以通过使用Reflector.NET看到:

public static IObservable<TSource> Start<TSource>(Func<TSource> function)
{
    if (function == null)
    {
        throw new ArgumentNullException("function");
    }
    return function.ToAsync<TSource>()();
}

public static Func<IObservable<TResult>> ToAsync<TResult>(
    this Func<TResult> function)
{
    if (function == null)
    {
        throw new ArgumentNullException("function");
    }
    return function.ToAsync<TResult>(Scheduler.ThreadPool);
}

因此,如果您希望订阅在UI线程上运行,则在调用ObserveOn之前,了解所使用的调度程序必须使用Subscribe形式。

此外,由于您使用的是Rx,我不会使用InvokeRequired - 这只是混合异步编码模型。 Rx拥有你需要很好地使用线程所需的一切。