C# 使用MVVM在relaycommand中运行异步方法
我正在使用WPF和MVVM开发一个异步应用程序,但似乎无法在我的relaycommand中运行异步方法 我的WPF视图上有一个按钮,连接到我的视图模型中的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
/// <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
委托中的实际错误行。我们能设法解决这个问题吗?