質問

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
}
役に立ちましたか?

解決

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);
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top