【发布时间】:2019-11-01 06:06:35
【问题描述】:
我的 WinForms 应用程序通过 WCF 连接到正在运行的服务并订阅来自该服务的事件。当事件触发时,我的应用程序从服务请求当前数据并调用名为 UpdateDisplay() 的方法来填充 DataGridView 并显示它。网格视图仍然是空的,我正在尝试调试它。但是,如果我在 UpdateDisplay() 中设置断点,则下次触发事件时,我会遇到死锁,因为第一个事件处理程序尚未完成。
我想我可以在我的方法顶部取消订阅该事件并在底部重新订阅它,如下所示:
private static bool m_updatingDisplay = false;
private void UpdateDisplay()
{
// Unsubscribe from the event while the display is being updated. This should remove the problem of deadlocks while debugging because
// the event gets raised again.
m_callbackHandler.DatabaseUpdatedEvent -= m_callbackHandler_DatabaseUpdatedEvent;
DoSomethingThatTakesALongTime();
m_callbackHandler.DatabaseUpdatedEvent += m_callbackHandler_DatabaseUpdatedEvent;
}
但我仍然得到异常。
我唯一的想法是让事件处理程序只设置一个标志,然后计时器会每分钟左右检查一次标志,如果它是真的,那么它会进行更新并清除标志。我认为这可行,但我觉得这是一个公认的解决方案的常见问题,我可能应该知道它是什么。处理这种情况的最佳方法是什么?
【问题讨论】:
-
你得到什么执行?这怎么会导致死锁?那个处理程序在做什么?
-
现在没有发生。叹。我讨厌我的程序在不应该运行的时候运行。
-
好的,现在我明白了。它发生在我退出第一个消息处理程序时。这是一个InvalidOperationException,并且异常弹出窗口说:“此操作将死锁,因为在当前消息完成处理之前无法接收到回复。如果要允许无序消息处理,请指定Reentrant的ConcurrencyMode或Multiple on回调行为属性。”我不想使用这些属性值,因为我不理解它们。相反,我只想停止处理更新事件。
-
您想错过在运行 DoSomethingThatTakesALongTime() 时发生的事件,还是要等到第一次更新完成后再处理该事件?例如: 1. 接收 DatabaseUpdatedEvent no 1 2. 开始处理 3. 完成加载(仍在) 4. DatabaseUpdatedEvent no 2 已发出信号但被忽略(因为我们仍在 DoSomethingThatTakesALongTime() 5. 完成更新 UI 6. 允许更多事件7. 很长一段时间没有来自 DB 的信号。您的 UI 现在显示陈旧数据(这在您的应用程序中可能没问题)
-
在这种特殊情况下,是的,我不关心丢失的事件。我的功能将完成,然后显示将更新。具体来说,我正在调试。我有一个断点,我试图用一组特定的数据仔细观察特定时间点的行为。我不希望触发一个改变我正在研究的数据集的新事件。不过,总的来说,我不知道从事件处理程序运行任务的最佳方法是什么,该事件处理程序在下一个事件触发时可能仍在运行。我怀疑第一个答案中提到的 invoke() 是最好的方法。