2016-06-14 5 views
1

Ich versuche, ReactiveUI 6.5 für WinForms zu verwenden.Wie mache ich ReactiveCommand synchron?

Ich brauche einen Befehl, der auf dem Viewmodel aufgerufen und synchron auf der Ansicht ausgeführt wird. Ich versuchte ReactiveCommand.Create() und .Execute(), aber das ist offensichtlich async ausgeführt, was ist nicht das, was ich brauche.

Was ich habe, ist so etwas wie diese:

public class MyViewModel : ReactiveObject 
{ 
    public ReactiveCommand<object> AddNewThingToControl { get; private set; } 

    public ThingType Thing { get; set; } 

    // Ctor 
    public MyViewModel() 
    { 
     AddNewThingToControl = ReactiveCommand.Create(); 
    } 

    // Thing factory, called from somwhere not shown 
    public void CreateAndAddThing() 
    { 
     Thing = new ThingType(); 

     // should not return before Thing is added to myControl 
     AddNewThingToControl.Execute(null); 

     // Code that needs Thing added to myControl goes here. 
     // This doesn't work because DoAddThing() has not been called yet! 
    } 
} 

public class MyView : Form, IViewFor<MyViewModel> 
{ 
    public MyViewModel VM { get; set; } 

    // Ctor 
    public MyView() 
    { 
     VM = new MyViewModel(); 
     VM.AddNewThingToControl.Subscribe(x => { DoAddThing(); }); 
    } 

    private void DoAddThing() 
    { 
     // This doesn't get called until some unknown time 
     // after AddNewThingToControl.Execute() returns! 
     myControl.Things.Add(VM.Thing);  
    } 

    // ----------- 
    #region IViewFor Implementation not shown 
} 

CreateAndAddThing() wird durch den Code entweder auf dem UI-Thread oder von irgendeiner Art von Worker-Thread genannt.

Eine neue Thing wird erstellt und sollte der Steuerung in der Ansicht hinzugefügt werden, bevor die Zeile nach AddNewThingToControl.Execute() erreicht wird.

Wie kann ich das mit ReactiveCommand?

Antwort

1
  • Geben Sie MethodThatNeedsThingAdded()Task zurück, um zu erwarten.
  • Die CreateAndAddThing() Methode async und await zuerst für die Ausführung des Befehls und dann für die MethodThatNeedsThingAdded().
  • Rufen Sie nicht Execute auf der ReactiveCommand, aber ExecuteAsyncTask, was zu erwarten ist!

Dies könnte der Code sein:

public async void CreateAndAddThing() 
{ 
    Thing = new ThingType(); 
    await AddNewThingToControl.ExecuteAsyncTask(null); 
    await MethodThatNeedsThingAdded(); 
} 

Diese Lösung ist elegant, klar, und Sie sind sicher, dass die beiden Methoden immer in der richtigen Reihenfolge aufgerufen werden. Die gesamte Arbeit ist also asynchron zum UI-Thread, aber sequenziell und vorhersagbar, wie Sie es möchten.

Sie werden sagen: "aber ich wollte, dass alle diese Runde synchron sein!". Haben Sie wirklich brauchen eine synchrone Ausführung? Für welchen Zweck? Wenn du wirklich brauchst, dann hast du die falsche Bibliothek gewählt. Versuchen Sie, eine eigene Klasse Command zu implementieren (abgeleitet von ICommand, wie von WPF-Steuerelementen benötigt).