[英]Running an async method inside a relaycommand using MVVM
我正在使用WPF和MVVM开发一个异步应用程序,但我似乎无法在我的relaycommand中运行异步方法。
我的WPF 视图上有一个按钮连接到我的viewmodel中的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;
}
}
但是,当relay命令尝试执行时,我收到以下异常:
mscorlib.dll中发生了未处理的“System.AggregateException”类型异常
附加信息:通过等待任务或访问其Exception属性未观察到任务的异常。 结果,终结器线程重新抛出了未观察到的异常。
我在这个帖子中尝试了很多东西来尝试解决问题而没有运气。 有谁知道如何解决这个问题?
不确定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();
}
}
}
好的,我实际上设法通过改变我运行异步方法的方式来解决问题。
我改变了这个:
var results = await DockFindModel.SearchAsync();
对此:
var results = await QueuedTask.Run(() => DockFindModel.SearchAsync());
虽然我有点困惑,为什么我需要在relaycommand已经接受异步lambda时等待Task.Run()。 不过我肯定会随着时间变得清晰。
感谢那些评论的人。
RelayCommand
类可能接受Action
类型的参数。 由于您传递的是异步lambda,因此我们在这里有一个async void
方案。 您的代码将被解雇并被忘记 。 考虑使用将Func<Task>
作为参数而不是Action
的ICommand实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.