我正在以MVC模式编写WPF应用程序。应用程序的目的是在数据库中显示一些数据,并且这些数据将异步更新。
我正在考虑如何设计架构,以便它是线程安全的。特别是:
显然,刚刚关闭的页面应取消订阅服务,而刚刚出现的页面应该(或可能)订阅。
我可以将订阅放在一个关键部分,以及广播新数据,但是想象一下下面的场景(页面〜=它的viewmodel,这里没什么关系):
这对我来说似乎是一个僵局。
如何安全地设计此体系结构以避免此类死锁?也许页面永远不会取消订阅?或者是否有另一种方法来保护线程,使它们不会死锁?
答案 0 :(得分:0)
鉴于该帖子被标记为WPF和WP-8.1以及评论中的澄清,我将执行以下操作:
INotifyPropertyChanged
ObservableCollection<BaseModel>
。该模型还应实现在构造函数中实例化的互斥锁/锁属性。lock
来自Model ObservableCollection的Add
或Remove
项的代码部分。此部分必须放在Dispatcher.Invoke()
或同等平台调用中。这可以确保它只是等待更新集合的UI线程。这样,UI和视图模型对特定服务事件不小心,从而消除了订阅的开销,并且如果共享模型,也限制了数据的重复 - 即使屏幕上有20个页面,您的服务也会执行单个更新,通过框架的功能(绑定)传播到UI和视图模型。
答案 1 :(得分:0)
一个简单的解决方案可能是:不要在UI线程中执行取消订阅操作。 (一般不要阻止UI线程。)以异步方式执行,触发并忘记。
或者你可以看看Rx (Reactive Extensions)究竟是出于什么目的:以多线程方式实现观察者模式。
默默地“只是不取消订阅”可能不是一个好主意。虽然我不知道您的实现细节,但如果事件处理程序是实例方法,那么服务将保留对该实例的隐式引用,并且根据引用链可能会阻止您的页面或其他实例进行垃圾回收。 / p>
“还是有另一种方法来保护线程,使它们不会死锁?”目前在.NET框架中没有什么神奇的技巧可以自动防止死锁。其他多线程环境可能会也可能不会提供自动死锁解决方案(注意:不会阻止)服务,它可以检测死锁(发生之后)并自动选择受害者。在.NET中,在等待资源时会发生异常。 (这还没有实现)