繁体   English   中英

没有Void方法的MVVM中的async / await

[英]async/await in MVVM without Void methods

我想在我的Windows Phone 8 MVVM项目上使用async / await,我正在努力找到一种使用这个api实现我的ICommands的好方法。 我一直在阅读一些关于这个主题的文章,我在下面的MSDN中提到了这个问题,其中指出我必须避免异步空洞,因为它很难捕获未处理的异常: http//msdn.microsoft.com/en -us / magazine / jj991977.aspx在另一个问我有关这个问题的问题,有人还说我不应该使用异步空洞。 除非有事件。

但问题是我可以在互联网上找到的所有例子都使用异步空洞。 我找到的这两篇文章是例子: http//richnewman.wordpress.com/2012/12/03/tutorial-asynchronous-programming-async-and-await-for-beginners/http://blog.mycupof.net / 2012/08/23 / MVVM-asyncdelegatecommand乜asyncawait灿做换uidevelopment /

最后一个是使用async / await的ICommand实现,但它也使用异步空洞。 我正在尝试为此提出解决方案,因此我基于RelayCommand编写了ICommand的这个实现:

public delegate Task AsyncAction();

public class RelayCommandAsync : ICommand
{
    private AsyncAction _handler;
    public RelayCommandAsync(AsyncAction handler)
    {
        _handler = handler;
    }

    private bool _isEnabled;
    public bool IsEnabled
    {
        get { return _isEnabled; }
        set
        {
            if (value != _isEnabled)
            {
                _isEnabled = value;
                if (CanExecuteChanged != null)
                {
                    CanExecuteChanged(this, EventArgs.Empty);
                }
            }
        }
    }

    public bool CanExecute(object parameter)
    {
        return IsEnabled;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        ExecuteAsync();
    }

    private Task ExecuteAsync()
    {
        return _handler();
    }
}

我试图像这样使用它:在构造函数中:

saveCommand = new RelayCommandAsync(SaveSourceAsync);

然后:

private async Task SaveSourceAsync()
{
    await Task.Run(() => { Save(); });
}

private void Save()
{
    // Slow operation
}

问题是我对这个和任何其他实现感到不舒服,因为我不知道哪个是最好和最优的。

任何人都可以说明我应该如何使用它,最好是使用MVVM?

在引用的文章中,我确实指出ICommand.Execute实际上是一个事件处理程序,因此它将被视为“避免async void ”指南的异常:

总结第一个指南,你应该更喜欢async Task to async void ...本指南的例外是异步事件处理程序,它必须返回void。 此异常包括逻辑事件处理程序的方法,即使它们不是字面上的事件处理程序(例如,ICommand.Execute实现)。

关于你的ICommand实现,它实际上通过使用async void引入了一个缺陷: ICommand.Execute实现将丢弃Task而不观察它的异常。 因此,该实现将忽略async委托引发的任何异常。

相反,您链接到的博客文章有一个async void ICommand.Execute await Task ,允许异常传播到UI同步上下文。 其中 - 在这种情况下 - 是所需的行为,因为它与同步ICommand.Execute引发异常时获得的行为相同。

如果您有这种倾向,我希望您尝试使用我编写的一两个ICommand ,以便将来可能包含在我的AsyncEx库中 第一个是一个简单的命令,非常类似于您发布的博客中的命令。 第二个是更完整的“异步命令”实现,包括取消,进度报告和CanExecute自动管理。 我很感激任何反馈。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM