c# - wpf mvvm 等待方法在使用 await 任务延迟进行模拟时阻止 UI

标签 c# wpf multithreading mvvm async-await

当我关注我的 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/

相关文章:

c# - 使 WPF DockPanel 根据其子项的大小自动调整大小的方法?

c# - Entity Framework 中的排序列属性

c# - Angular 到 C# Http 传递查询参数

c# - 如何使用 CURL 或 ARC 向受 Azure AD 授权保护的 Web Api 发出请求

c++ - 将函数调用保存在容器中

wpf - 使用 Task 与 Dispatcher 进行 ui 线程操作

c# - 当 ChromiumWebBrowser 被处置时,CefSharp.BrowserSubprocess 没有关闭

wpf - 如何在 DataGrid 中的多个选定行上执行命令?

c# - 如何在代码隐藏中绑定(bind)到 Canvas.Left 或 Canvas.Top 附加属性?

java - Android FileChannel 在不同的 AsyncTask 中读写失败