如何在mvvmcross视图模型中使用async?

Chr*_*iak 26 c# async-await mvvmcross xamarin

我在mvvmcross viewmodel中有一个长时间运行的进程,并希望将其设置为异步(http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx).

Xamarin的测试版渠道目前支持async关键字.

下面是我目前如何实现异步的示例.IsBusy标志可以绑定到UI元素并显示加载消息.

这是正确的方法吗?

public class MyModel: MvxViewModel
{
    private readonly IMyService _myService;
    private bool _isBusy;

    public bool IsBusy
    {
        get { return _isBusy; }
        set { _isBusy = value; RaisePropertyChanged(() => IsBusy); ; }
    }

    public ICommand MyCommand
    {
        get
        {
            return new MvxCommand(DoMyCommand);
        }
    }

    public MyModel(IMyService myService)
    {
        _myService = myService;
    }

    public async void DoMyCommand()
    {
        IsBusy = true;
        await Task.Factory.StartNew(() =>
            {
                _myService.LongRunningProcess();
            });
        IsBusy = false;
    }

}
Run Code Online (Sandbox Code Playgroud)

Ste*_*ary 30

你应该避免async void.当你正在处理时ICommand,你需要使用async void,但它的范围应该最小化.

此修改后的代码将您的操作公开为async Task,可以从代码的其他部分进行单元测试和消耗:

public class MyModel: MvxViewModel
{
  private readonly IMyService _myService;
  private bool _isBusy;

  public bool IsBusy
  {
    get { return _isBusy; }
    set { _isBusy = value; RaisePropertyChanged(() => IsBusy); ; }
  }

  public ICommand MyCommand
  {
    get
    {
      return new MvxCommand(async () => await DoMyCommand());
    }
  }

  public MyModel(IMyService myService)
  {
    _myService = myService;
  }

  public async Task DoMyCommand()
  {
    IsBusy = true;
    await Task.Run(() =>
    {
      _myService.LongRunningProcess();
    });
    IsBusy = false;
  }
}
Run Code Online (Sandbox Code Playgroud)

你的使用IsBusy很好; 这是异步UI中的一种常见方法.

我确实改变Task.Factory.StartNewTask.Run; 由于Stephen Toub所描述的原因,Task.Runasync代码中是首选.

  • `async` lambda为您提供略有不同的错误处理.使用`()=> DoMyCommand()`,可以静默地吞下来自`DoMyCommand`的任何异常.使用`async()=>等待DoMyCommand()`,来自`DoMyCommand`的任何异常都被视为未处理的异常. (3认同)

Col*_*con 6

MvvmCross现在有MvxAsyncCommand(参见GitHub 提交).

所以不要这样做

public ICommand MyCommand
{
  get
  {
    return new MvxCommand(async () => await DoMyCommand());
  }
}
Run Code Online (Sandbox Code Playgroud)

你可以这样做

public ICommand MyCommand
{
  get
  {
    return new MvxAsyncCommand(DoMyCommand);
  }
}
Run Code Online (Sandbox Code Playgroud)