Reputation: 355
I have a problem running a method (based on ToObservable
) on a non UI-thread in a WPF-application.
For example I have this method:
public IObservable<ViewModel> Get()
{
IEnumerable<ViewModel> vms = _repository.Get();
Thread.Sleep(2000);
return vms.ToObservable();
}
I use this method in the ViewModel:
manager.Get()
.ObserveOnDispatcher()
.SubscribeOn(new NewThreadScheduler())
.Subscribe(result =>
{
Data.Add(result);
});
The problem is that method Get
is executed on the UI/Main thread but I need to run this method on a non-UI thread.
Upvotes: 0
Views: 428
Reputation: 117027
I would suggest making the call to manager.Get()
to be made inside Observable.Start
and then just do a .Merge()
to bring the IObservable<IObservable<ViewModel>>
back to a IObservable<ViewModel>
.
Try this:
Observable
.Start(() => manager.Get(), Scheduler.Default)
.Merge()
.ObserveOnDispatcher()
.SubscribeOn(new NewThreadScheduler())
.Subscribe(result =>
{
Data.Add(result);
});
The .SubscribeOn(new NewThreadScheduler())
probably isn't necessary.
Upvotes: 1
Reputation: 14350
You have the right idea. However, in order to use the ObserveOn
and SubscribeOn
operators effectively, you need to have an observable source. In your example, it doesn't appear that you have that. Once you get that, you can do this:
IObservable<TAnything> source;
source
.ObserveOn(Scheduler.ThreadPool)
.SelectMany(_ => Get())
.ObserveOn(DispatcherScheduler.Instance)
.Subscribe(result =>
{
Data.Add(result);
});
In your case, source
will most likely be an observable generated from a button-click or some other event.
ObserveOn
schedules code that follows it for the given scheduler. So in our case, the first ObserveOn
call makes the code that follows happen on the ThreadPool (non-UI). The second ObserveOn
makes the code happen on the dispatcher (UI).
SubscribeOn
makes subscription-time code happen on a given scheduler. Since your code sample didn't have anything interesting happening at subscription-time, it makes sense to drop it.
Upvotes: 0