c# - 等待时调用 RaiseCanExecuteChanged 导致死锁

标签 c# asynchronous prism async-await prism-4

我正在使用 PRISM 的 WPF 和 DelegateCommand 并遇到以下问题:

我开始一个异步操作,例如:

public async void ProgramDevice()
{
    var result = await FirmwareLoader.DownloadFirmwareAsync();
}

在此方法中,触发了我注册的事件,应该更新我的 DelegateCommand 以使其无法执行:

//UiCommand is of type DelegateCommand
Engine.IsProgrammedChanged += 
    (s, e) => Dispatcher.Invoke(() => UiCommand.RaiseCanExecuteChanged());

现在我遇到了问题,RaiseCanExecuteChanged 导致死锁(我检查过并且 Dispatcher.Invoke 不会导致它,因为当我例如显示 MessageBox 时它工作正常)。

我是不是做错了什么或者我该如何解决这个问题?

最佳答案

我看到您已经解决了您的问题,但我想我会提供一个更通用的解决方案,以帮助您防止将来出现此类死锁。

在您的情况下,您可以使用 ConfigureAwait 轻松避免这种死锁。像这样:

var result = await FirmwareLoader.DownloadFirmwareAsync().ConfigureAwait(false);

这样做是允许继续在与原始线程不同的线程上执行。这样做并不总是可行的,因为很多时候您需要在 UI 线程上执行延续,但对于这个问题,我认为情况并非如此。所以基本上,最佳做法是始终使用 ConfigureAwait(false),除非您需要从原始线程恢复执行。

This article详细解释了为什么会发生这种死锁以及如何避免它们。另一个推荐读物是 Best Practices in Asynchronous Programming .

关于c# - 等待时调用 RaiseCanExecuteChanged 导致死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18654558/

相关文章:

c# - 为在 C# 中不返回任何值的方法创建单元测试用例

c# - 来自 textBox 的值没有被插入到数据库中

c# - Xamarin Android Visualizer SetDataCaptureListener 抛出 InvalidCastException

javascript - Jasmine beforeEach 不等待完成回调

c# - 是否可以在没有任何人的情况下执行异步操作 "knowing"?

wpf - 基类 `Application` 在一种解决方案中未被识别为类型

c# - 通过 DllImport 调用非托管函数时堆损坏

grails - 在Grails中,可以有一个带有waitFor标签的 View 吗?

c# - 使用另一个类的 EventAggregator 在 Window 的 ViewModel 中刷新属性

c# - PRISM中的复合 View 导航