2017-07-28 51 views
0

不冻结WPF MVVM等待方法阻塞UI,同时与模拟等待当我跟着我的UI任务迟迟不

XAML绑定:

<Button Command="{Binding LongRunningCommand}" /> 

视图模型:

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 冻结。这太奇怪了。看看下面的例子:

XAML绑定:

<Button Command="{Binding LongRunningCommand}" /> 

视图模型:

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 IMPL:

public Task LongRunningMethod(object e) 
{ 
    return Task.Run(() => 
    { 
     ... 
    } 
} 

有人可以看到我在做什么错了,请,我在这上面花了很多时间...

顺便说一句,我知道async void不是一个最佳做法,但我找不到解决方案,使DelegateCommand异步。

编辑

更多的研究后,我们得出的结论是,这是一个“渲染”的问题。 LongRunningCommand是异步的,但渲染和绑定需要时间并阻止UI。我不知道如何解决这个渲染问题。

+0

它可以冻结的情况下_adjust viewmodel observablecollection与callResult_做一些沉重的UI更新 – Fabio

+0

我只是用200个结果填充observablecollection它阻止我的窗口。我不能移动窗口,也不能调整大小1秒。 – Ozkan

+2

你有看过[这篇文章来自MSDN](https://msdn.microsoft.com/en-gb/magazine/dn630647.aspx)吗? – XAMlMAX

回答

2

这个等待死锁的任务在我找到解决方案之前很长一段时间也一直困扰着我。

更换

var callResult = await _dbAccess.LongRunningMethod(); 

var callResult = await _dbAccess.LongRunningMethod().ConfigureAwait(false); 

的详细信息,请参见为什么通过this blog post斯蒂芬·克利里。

请注意,await之后的延续现在将位于不同的调度程序上下文中,因此必须将任何直接更新UI的内容(例如填充可观察集合)整理回UI调度程序。许多MVVM框架包含实用程序来帮助解决这个问题 - 我使用MVVM Light中的DispatcherHelper类。

如果您使用的是Resharper,那么您可以安装一个插件来检查ConfigureAwait()是否添加到每个await语句中。

+0

OP没有提到关于死锁。 – Fabio

+2

“但是,如果我用一个真正的方法替换Task.Delay,那么我的UI会冻结”......正是一个僵局。 – Peregrine

+0

这很可能是OP解决问题的方法。虽然我会使用一个configureawait分析器附加到该项目。这就是我们所做的。不希望构建链依赖VS扩展来确保安全代码 – Dbl