使用 MVVM 在中继命令中运行异步方法

pvd*_*dev 2 c# wpf mvvm async-await

我正在使用 WPF 和 MVVM 开发异步应用程序,但我似乎无法在我的中继命令中运行异步方法。

我的 WPF视图上有一个按钮连接到我的viewmodel 中的中继命令,它尝试在我的模型中调用异步方法以返回结果列表:

/// <summary>
/// Search results 
/// </summary>
private ObservableCollection<string> _searchResults = new ObservableCollection<string>(); 
public IList<string> SearchResults
{
    get { return _searchResults; }
}

/// <summary>
/// Search button command
/// </summary>
private ICommand _searchCommand;
public ICommand SearchCommand
{
    get
    {
        _searchCommand = new RelayCommand(
            async() =>
            {
                SearchResults.Clear();
                var results = await DockFindModel.SearchAsync(_selectedSearchableLayer, _searchString);
                foreach (var item in results)
                {
                    SearchResults.Add(item);
                }                    
                //notify results have changed
                NotifyPropertyChanged(() => SearchResults);
            },
            () => bAppRunning); //command will only execute if app is running
        return _searchCommand;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,当中继命令尝试执行时,我收到以下异常:

mscorlib.dll 中发生类型为“System.AggregateException”的未处理异常

附加信息:等待任务或访问其 Exception 属性均未观察到任务的异常。结果,未观察到的异常被终结器线程重新抛出。

我在这个线程中尝试了很多东西来尝试解决这个问题,但没有运气。有谁知道如何解决这个问题?

Cam*_*and 7

不确定您的 RelayCommand 来自何处(MVVM 框架或自定义实现),但请考虑使用异步版本。

public class AsyncRelayCommand : ICommand
{
    private readonly Func<object, Task> execute;
    private readonly Func<object, bool> canExecute;

    private long isExecuting;

    public AsyncRelayCommand(Func<object, Task> execute, Func<object, bool> canExecute = null)
    {
        this.execute = execute;
        this.canExecute = canExecute ?? (o => true);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void RaiseCanExecuteChanged()
    {
        CommandManager.InvalidateRequerySuggested();
    }

    public bool CanExecute(object parameter)
    {
        if (Interlocked.Read(ref isExecuting) != 0)
            return false;

        return canExecute(parameter);
    }

    public async void Execute(object parameter)
    {
        Interlocked.Exchange(ref isExecuting, 1);
        RaiseCanExecuteChanged();

        try
        {
            await execute(parameter);
        }
        finally
        {
            Interlocked.Exchange(ref isExecuting, 0);
            RaiseCanExecuteChanged();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)