如何使MvvmLight命令异步? [英] How do I make an MvvmLight command async?

查看:473
本文介绍了如何使MvvmLight命令异步?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

仍然让我不停地等待/异步,并且很难了解如何在MVVM设置中使用它.我正在使用MvvmLight,但我想这个问题也适用于任何其他MVVM框架.

Still getting my head around await/async, and am having difficulty seeing how I use it in an MVVM setting. I'm using MvvmLight, but I imagine the question applies to any other MVVM framework.

假设我有一个显示宠物列表的WPF应用程序.我有一个RefreshCommand,它可以从WCF服务中刷新列表. UI上有一个指示器来表明它正忙,并且已绑定到视图模型上的IsBusy bool属性.我的命令代码目前看起来像这样...

Suppose I have a WPF application that shows a list of pets. I have a RefreshCommand, that refreshes the list from a WCF service. The UI has an indicator to show that it's busy, and this is bound to an IsBusy bool property on the view model. My command code currently looks like this...

  BackgroundWorker bw = new BackgroundWorker();
  IsBusy = true;
  bw.DoWork += (_, __) => {
    Pets = _petService.GetPets();
    IsBusy = false;
  };
  bw.RunWorkerAsync();

宠物是视图模型上的ObservableCollection属性.

Pets is an ObservableCollection property on the view model.

我想使用await/async关键字,并取消使用BackgroundWorker.我搜索并阅读,阅读并搜索,并感到困惑.我见过的大多数文章/博客文章/等等似乎都要求您创建自己的ICommand异步实现.为什么这是必要的?鉴于MVVM和ICommand内置于.NET框架中,因此肯定也应内置对它们使用async/await的功能,而无需创建我们自己的异步命令类.

I want to use the await/async keywords, and do away with the BackgroundWorker. I've searched and read, and read and searched, and am getting confused. Most of the articles/blog posts/etc I've seen seem to require you to create your own async implementation of ICommand. Why is this necessary? Given that MVVM and ICommand are built-in to the .NET framework, surely the ability to use async/await with them should also be built-in, without the need to create our own async command class.

我错过了什么吗,或者这真的是唯一的方法吗?

Have I missed something, or is this really the only way to do it?

我尝试了以下操作,但是没有用...

I tried the following, but it didn't work...

  private async void LoadAsyncData() {
    IsBusy = true;
    Task<ObservableCollection<Pet>> t = GetPetsAsync();
    Pets = await t;
    IsBusy = false;
  }

  private async Task<ObservableCollection<Pet>> GetPetsAsync() {
    await Task.Delay(1);
    return _petService.GetPets();
  }

我将调用添加到Task.Delay(1),因为编译器警告我该方法将称为同步.

I added the call to Task.Delay(1) as the compiler warned me that the method would be called sync.

已加载数据,但是UI从未响应IsBusy属性的更改,因此用户看不到UI忙.

The data loaded, but the UI never responded to the IsBusy property being changed, so the user doesn't see that the UI is busy.

有人能提供建议吗?

推荐答案

您最好听一下编译器警告您的内容,而不是将其隐藏起来:)之后,无用的await Task.Delay方法将在UI线程上继续,因此基本上还是同步方法-这就是为什么UI没有响应IsBusy属性,它被阻止的原因.相反,您必须要么

You better listen to what compiler warns you about instead of getting that under the carpet :) After that useless await Task.Delay method will continue on UI thread and so it's basically synchronous method still - that is why UI did not respond to IsBusy property, it was blocked. Instead you have to either

  • 在后台线程上明确运行_petService.GetPets:

private async void LoadAsyncData() {
   IsBusy = true;
   Pets = await Task.Run(() => _petService.GetPets());
   IsBusy = false;
}

  • (更好),通过添加异步版本的GetPets来更改您的petService:

  • (better) Change your petService by adding asynchronous version of GetPets:

    private async void LoadAsyncData() {
       IsBusy = true;
       Pets = await _petService.GetPetsAsync();
       IsBusy = false;
    }
    

  • 这篇关于如何使MvvmLight命令异步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆