Вам необходимо ознакомиться с планировщиком по умолчанию, используемым различными методами Rx.
Методы, подобные Observable.Generate
, выполняются в потоке, который подписывается на наблюдаемое.
С другой стороныС другой стороны, цель метода Observable.Start
состоит в том, чтобы асинхронно вызывать действие lamdba при подписке на наблюдаемое.Это не будет асинхронным, если это произойдет в потоке пользовательского интерфейса.Так что в этом случае он использует планировщик 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);
}
Итак, зная используемый планировщик, вы должны использовать форму ObserveOn
перед вызовом Subscribe
, если вы хотите, чтобы подписка работала в потоке пользовательского интерфейса.
Кроме того, поскольку вы используете Rx, я бы не стал использовать InvokeRequired
- это просто смешивание моделей асинхронного кодирования.Rx имеет все, что вам нужно, чтобы красиво играть с потоками.