【发布时间】:2015-01-04 07:49:20
【问题描述】:
我正在以 MVC 模式编写 WPF 应用程序。应用程序的目的是显示数据库中的一些数据,这些数据是异步更新的。
我正在考虑如何设计架构,使其成为线程安全的。特别是:
- 每个页面(或其视图模型)必须能够订阅和取消订阅服务,这会更新数据库。
- 更新数据库的服务会通知所有订阅者,新数据已到达,他们应该刷新他们的视图。
显然,刚刚关闭的页面应该取消订阅服务,而刚刚出现的页面应该(或可能)订阅。
我可以将订阅放在关键部分中,以及广播新数据,然后想象以下场景(页面 ~= 它的视图模型,这在此处无关紧要):
- 服务进入关键部分以广播有关新数据的信息(在单独的线程中)
- 页面尝试进入临界区以取消订阅(在主线程中)
- 服务将新数据通知页面(在单独的线程中)。
- 页面填充其字段并引发 PropertyChange 事件(在单独的线程中)。
- PropertyChange 事件被编组到主线程。等待关键部分。
在我看来,这就像一个僵局。
如何安全地设计此架构以避免此类死锁?也许页面永远不应该取消订阅?或者是否有其他方法可以保护线程不会死锁?
【问题讨论】:
-
这看起来真的很奇怪。具体来说,“服务”如何知道某些数据是新的?是不是因为刚刚被自己的app提交了?
-
为什么主线程需要获取临界区? (在最后一个要点)?另外,为什么在持有锁的同时触发事件?这很可能导致死锁!此外,一些演示问题的代码也会有所帮助。
-
一般来说,one 资源不会出现死锁。要出现死锁,您必须有 2 个或更多受保护的资源,并且阻塞 -> 阻塞图中的封闭循环。您使用“关键部分”术语(这不是问题),但您必须明确您使用什么保护/互斥/信号/等,您有 2 个或更多还是只有一个。我的猜测是,在取消订阅代码部分运行(在主 UI 线程中)之后,编组(排队)的 PropertyChange 将运行而没有死锁。当然,如果数据结构无效,这可能会导致问题,但这与死锁无关。
-
@zaitsman:服务无法知道,这就是为什么它是 polling(我想)。 Spook 的架构服务器隐藏这种丑陋的轮询(来自数据库环境),并将轮询转换为事件驱动的方法。
-
@g.pickardou 这就是你阅读它的方式,以及我最初阅读它的方式。但我想在这一点上得到 OP 的确认。答案将有助于确定正确的方法。
标签: c# wpf multithreading windows-phone-8.1