请参阅以下代码:
var obs = Observable.Start(() => LongRunningMethodToRetrieveData());
obs.Subscribe(x => MethodThatMustBeOnUIThread(x));
如果我确定在UI线程上执行了这两行代码,是否需要先调用ObserveOn(SynchronizationContext.Current)
?或者类似地,我是否需要检查InvokeRequired
内的MethodThatMustBeOnUIThread
?
基本上,我保证使用这两行代码可以在创建订阅的线程上调用'OnNext'吗?
感谢。
编辑:嗯,我在调试器中尝试过并且确实从后台线程调用了'MethodThatMustBeOnUIThread'。为什么是这样?我现在的假设是默认情况下会在运行异步方法的线程上发生观察。
答案 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拥有你需要很好地使用线程所需的一切。