I have a winform application, and an observable set up like this:
Form form = new Form();
Label lb = new Label();
form.Controls.Add(lb);
Observable.Interval(TimeSpan.FromSeconds(1))
.Subscribe(l => lb.Text = l.ToString());
Application.Run(form);
This doesn't work, since the l => lb.Text = l.ToString()
will not be run on the main thread which created the form, but I cannot figure out how to make it run on this thread. I assume, that I should use IObservable.SubscribeOn
which takes either an IScheduler
or a SynchronizationContext
, but I don't know how to get the synchronizationcontext of the main thread, and the only Schedulers I could find were the static properties of Scheduler
, such as Scheduler.CurrentThread
, Immediate
, NewThread
, TaskPool
and ThreadPool
, none of which worked.
My Rx version is 1.0.10621.
Just after I post the question, I find the solution:
Form form = new Form();
Label lb = new Label();
form.Controls.Add(lb);
Observable.Interval(TimeSpan.FromSeconds(2))
.ObserveOn(SynchronizationContext.Current)
.Subscribe(l => lb.Text = l.ToString());
Application.Run(form);
This link was helpful. Two notes:
ObserveOn
, not SubscribeOn
. At the moment, I don't know enough about this to know why, so any links in the comments would be appreciated.edit: Thanks to the first part of this link, I now understand more about the difference between ObserveOn
and SubscribeOn
. In short:
OnNext
and friends) from that context. In my example, I observe on the main/UI thread, so therefore I get no cross thread exceptionsSubscribeOn
is a little more complicated, so here is an example: Concat takes a number of observables and combines them to one long observable. Once an observable calls OnCompleted
, the combined observable will dispose of that subscription, and subscribe to the next observable. This all happens on the thread that called OnCompleted
, but there can be some problems with subscribing to observables, that were created by Observable.FromEvent
, e.g. Silverlight will throw if you add an event handler from another thread than the UI thread, and WinForms and WPF will throw if you add a event handlers from multiple different threads. SubscribeOn
will let you control the thread on which your observable hooks up to the underlying event.