如何使ReactiveCommand同步?

时间:2016-06-14 13:40:43

标签: winforms reactiveui

我正在尝试将ReactiveUI 6.5用于WinForms。

我需要一个在viewmodel上调用并在视图上同步执行的命令。我尝试了ReactiveCommand.Create().Execute(),但这显然是异步执行的,这不是我需要的。

我所拥有的是这样的:

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
}
代码在UI线程或某种工作线程上调用

CreateAndAddThing()

创建了一个新的Thing,应该在到达AddNewThingToControl.Execute()之后的行之前将其添加到视图中的控件上。

如何使用ReactiveCommand

执行此操作

1 个答案:

答案 0 :(得分:1)

  • Make MethodThatNeedsThingAdded() to return Task, in order to be awaitable.
  • Make the CreateAndAddThing() method async, and await first for the execution of the command, and then for the MethodThatNeedsThingAdded().
  • Don't call Execute on the ReactiveCommand, but ExecuteAsyncTask which is awaitable!

This could be the code:

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

This solution is elegant, clear, and you're sure that the two methods are always called in the right order. So to speak, the whole work is asynchronous respect to the UI Thread, but is sequential and predictable as you want.

You will say: "but I wanted all this round to be synchronous!". Do you really need a synchronous execution? For what purpose? If you really need this, imho you've chosen the wrong library. Try to implement a Command class on your own (deriving from ICommand as needed by WPF controls).