当我关注我的 UI 不会卡住 :
xml绑定(bind):
<Button Command="{Binding LongRunningCommand}" />
View 模型:
ctor
{
LongRunningCommand = new DelegateCommand<object>(ProcessLongRunningCommand);
}
public DelegateCommand LongRunningCommand { get; private set; }
private async void ProcessLongRunningCommand(object e)
{
await Task.Delay(5000);
}
但是如果我用真正的方法替换 Task.Delay,那么我的 UI 卡住 .这太奇怪了。看下面的例子:
xml绑定(bind):
<Button Command="{Binding LongRunningCommand}" />
View 模型:
private readonly IDbAccess _dbAccess;
ctor(IDbAccess dbAccess)
{
_dbAccess = dbAccess
LongRunningCommand = new DelegateCommand<object>(ProcessLongRunningCommand);
}
public DelegateCommand LongRunningCommand { get; private set; }
private async void ProcessLongRunningCommand(object e)
{
var callResult = await _dbAccess.LongRunningMethod();
//adjust viewmodel observablecollection property which binds to a ListBox with callResult
}
DbAccess 实现:
public Task LongRunningMethod(object e)
{
return Task.Run(() =>
{
...
}
}
有人可以看看我做错了什么吗,我在这方面浪费了很多时间......
顺便说一句,我知道
async void
不是最佳实践,但我找不到使 DelegateCommand 异步的解决方案。编辑
经过更多研究,我们得出结论,这是一个“渲染”问题。 LongRunningCommand 是异步的,但渲染和绑定(bind)需要时间并且会阻塞 UI。我不知道如何解决这个渲染问题。
最佳答案
这个等待死锁的任务也让我陷入了很长时间,直到我找到了解决方案。
代替
var callResult = await _dbAccess.LongRunningMethod();
和
var callResult = await _dbAccess.LongRunningMethod().ConfigureAwait(false);
见 this blog post Stephen Cleary 详细了解原因。
请注意,等待之后的继续现在将在不同的调度程序上下文中,因此任何直接更新 UI(例如填充可观察集合)的内容都必须编码回 UI 调度程序。许多 MVVM 框架包含实用程序来帮助解决这个问题 - 我使用 MVVM Light 的 DispatcherHelper 类。
如果您使用的是 Resharper,您可以安装一个插件来检查 ConfigureAwait() 是否已添加到每个 await 语句中。
关于c# - wpf mvvm 等待方法在使用 await 任务延迟进行模拟时阻止 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45371487/