Question

I am new to RX and I'm trying to adapt it to my WinForms application. (Un?)fortunately I use MVP pattern where the View is abstracted from any specific implementation (e.g. WinForms).

When RX-friendly Model produces new value, presenter gets it and tries to update the view. The problem is that I cannot observe on the main thread since I have no reference to WinForms Control.

I found a few solutions but neither of them looks well to me:

  1. Create a Control property in the view so that I could observe on it.
  2. Use Control.Invoke inside property setters which are modified by the Presenter
  3. Create an extension method similar to:

:

public static IObservable<T> ObserveOn<T>(this IObservable<T> observable, IMyView view)
{
    var control = (Control)view;
    return observable.ObserveOn(control);
}

Is there a nice way to handle this?

EDIT: I found another solution which I like the most:

private readonly SynchronizationContext _syncContext;

public Presenter()
{
    _syncContext = SynchronizationContext.Current; //I can observe on this one with a reasonable assumption that presenter is created on the UI thread
}
Was it helpful?

Solution

Is the presenter running on the UI thread at the time that it subscribes to the model? Just use ObserveOnDispatcher at the time your present subscribes to the observable:

// from your presenter code, which is running on the UI thread:
model.ObservableProperty.ObserveOnDispatcher().Subscribe(p => updateView(p));

Edit:

Alternatively, you can get Rx-Windows Forms Helper and have your IMyView interface expose an IScheduler (which it creates by calling new ControlScheduler(control)).

Then you can implement your ObserveOn(observable, view) extension method as:

public static IObservable<T> ObserveOn<T>(this IObservable<T> observable, IMyView view)
{
    return observable.ObserveOn(view.Scheduler);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top