我正在使用 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/