2012-01-30 43 views
3

请看下面的代码:使用ObserveOn观察物的必要性?

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

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

如果我敢肯定,这2行代码都在UI线程上执行,是否有必要先调用ObserveOn(SynchronizationContext.Current)?或者同样,我是否需要检查MethodThatMustBeOnUIThread内部的InvokeRequired

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

谢谢。

编辑:好吧,我试着在调试器和'MethodThatMustBeOnUIThread'确实是从后台线程调用。为什么是这样?我现在的假设是观察在默认情况下在运行异步方法的线程上发生。

回答

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拥有你需要用线程很好地玩的一切。