C# 使用MVVM在relaycommand中运行异步方法

C# 使用MVVM在relaycommand中运行异步方法,c#,wpf,mvvm,async-await,C#,Wpf,Mvvm,Async Await,我正在使用WPF和MVVM开发一个异步应用程序,但似乎无法在我的relaycommand中运行异步方法 我的WPF视图上有一个按钮,连接到我的视图模型中的relaycommand,它尝试调用我的模型中的异步方法以返回结果列表: /// <summary> /// Search results /// </summary> private ObservableCollection<string> _searchResults = new ObservableC

我正在使用WPF和MVVM开发一个异步应用程序,但似乎无法在我的relaycommand中运行异步方法

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

/// <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;
    }
}
//
///搜索结果
/// 
私有ObservableCollection_searchResults=新ObservableCollection();
公共IList搜索结果
{
获取{return\u searchResults;}
}
/// 
///搜索按钮命令
/// 
专用ICommandu searchCommand;
公共ICommand SearchCommand
{
得到
{
_searchCommand=newrelaycommand(
异步()=>
{
SearchResults.Clear();
var results=await DockFindModel.SearchAsync(\u selectedSearchableLayer,\u searchString);
foreach(结果中的var项目)
{
搜索结果。添加(项);
}                    
//通知结果已更改
NotifyPropertyChanged(()=>搜索结果);
},
()=>bAppRunning);//仅当应用程序正在运行时才会执行命令
返回搜索命令;
}
}
但是,当relaycommand尝试执行时,会出现以下异常:

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

其他信息:也未观察到任务的异常 通过等待任务或访问其Exception属性。作为一个 结果,未观察到的异常被终结器线程重新调用


我尝试了很多方法来解决这个问题,但都没有成功。有人知道如何解决这个问题吗?

好的,所以我实际上通过改变我运行异步方法的方式来解决这个问题

我改变了这一点:

var results = await DockFindModel.SearchAsync();
为此:

var results = await QueuedTask.Run(() => DockFindModel.SearchAsync());
尽管我有点困惑,为什么我需要等待Task.Run(),而relaycommand已经接受了异步lambda。不过,我相信随着时间的推移,事情会变得明朗起来


感谢那些评论的人

> P>不确定您的中继命令来自哪里(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();
        }
    }
}
公共类AsyncRelayCommand:ICommand
{
私有只读函数执行;
私有只读功能可执行;
私人长期执行;
公共AsyncRelayCommand(Func-execute,Func-canExecute=null)
{
this.execute=execute;
this.canExecute=canExecute??(o=>true);
}
公共事件事件处理程序CanExecuteChanged
{
添加{CommandManager.RequerySuggested+=value;}
删除{CommandManager.RequerySuggested-=value;}
}
public void raisecancecutechanged()
{
CommandManager.InvalidateRequestSuggested();
}
公共布尔CanExecute(对象参数)
{
如果(联锁读取(参考执行)!=0)
返回false;
返回canExecute(参数);
}
公共异步void Execute(对象参数)
{
联锁交换(参考执行,1);
RaiseCanExecuteChanged();
尝试
{
等待执行(参数);
}
最后
{
联锁交换(参考执行,0);
RaiseCanExecuteChanged();
}
}
}

RelayCommand
类可能正在接受类型为
Action
的参数。因为您正在传递一个异步lambda,所以这里有一个
异步void
场景。
您的代码将被触发并忘记。考虑使用一个ICOMMAN实现,以<代码> FUNC < /代码>作为参数,而不是<代码>动作< /代码>。< /P>内部异常是什么?您的中继命令看起来像什么?修复它!无论如何,谢谢各位。修复了还是躲闪了?我知道我在这里唤醒了一个旧线程,但你不应该等待lambda函数吗?我会尝试将
async()=>
更改为
async()=>await
。如果
execute
中存在异常,visual studio调试器将突出显示
await execute(参数)行。我希望调试器突出显示
execute
委托中的实际错误行。我们能设法解决这个问题吗?