我最近阅读了Head First Design Patterns书,我特别喜欢MVC这一章似乎从前面的章节中将所有内容整合在一起。但是,我现在即将实现一个MVC模式(在C ++中使用wxWidgets),我开始意识到我并不像我应该那样理解线程问题。
我有一个必须在模型更改时不断更新的视图,但是,用户可以与Control交互并影响模型。由于View / Control和Model将在2个不同的线程中运行(或者它是3?),我如何确保没有两个线程写入同一个数据对象?我是否负责设置共享数据的锁定?或者我只是在某种程度上保证不会有任何问题,只要我正确使用事件框架?
答案 0 :(得分:4)
MVC最初被认为是基于消息的系统(Smalltalk),在某种意义上它与多线程相反。
我知道如何结合MVC和多线程的最佳(理论)方式是活动对象(或actor)概念:对象存在于其自己的线程中,可以向其他活动对象发送/接收消息/事件。这假设对象上的所有操作都是同步的 - 因为单个对象绑定到单个线程 - 什么是每个对象互斥锁的类似物。
我有一个必须在模型更改时不断更新的视图,但是,用户可以与Control交互并影响模型。由于View / Control和Model将在2个不同的线程中运行(或者它是3?),
我没有使用wxWidgets的经验,但通常应用程序的GUI部分是单线程(apparently valid for wxWidgets too),只在主线程中运行。
View和Controller是UI绑定的,因此必须在主线程中运行。使用模型的额外线程使其成为2。
如何确保我没有两个线程写入同一个数据对象?
每个对象的互斥锁。
我是否负责设置共享数据的锁定?
是
或者只要我正确地使用事件框架,我只是保证不会有任何问题?
没有。如上所述,GUI是单线程的。如果你开始拥有自己的线程,那么你必须处理同步。
如果从主/ GUI线程触发其他线程中的操作,那么显然您需要同步对共享数据的访问。如果其他线程想要访问GUI,那么你必须使用特殊功能(在链接文章中提到)来触发主GUI线程中的事件(例如,模型在后台线程中更新,View必须在主线程中重绘它)。
如果后台线程不断更新模型,那么显然必须特别注意线程不会一直锁定互斥锁,以便View运行的主线程GUI也可以访问模型。 (某种readers-writer lock是可取的。)必须禁用控制器,因为如果应用程序在后台执行某些操作,则可能不希望用户交互。
总的来说,我认为最好将MVC保留在主线程中。 GUI线程不会产生太多CPU负载,并且空闲事件(wx has them too)通常足以模拟后台作业。
答案 1 :(得分:0)
理论上你可以在一个线程中运行MVC,但一般来说是的,你应该在适当的地方有锁。
在最简单的情况下,您可以为模型提供一个全局互斥锁,每个线程在需要执行某些操作时会接收该互斥锁。如果您希望模型连续运行但被控制器中断并且只要他们想要执行某些操作,那么单个互斥锁仍然有效,但是您需要在循环中放置一个点。