Osw*_*ald 7 language-agnostic architecture multithreading desktop-application
我正在编写一个多线程桌面应用程序.
我不确定多线程对架构的影响.有很多关于架构的文献,但我知道没有考虑多线程的文献.有很多关于多线程(互斥,信号量等)的低级文献的文献,但我知道没有描述这些概念是如何嵌入到架构中的.
您建议哪些文献填补这一空白?
我的申请包括
Presentation
使用GUI工具包创建和管理对话框,Kernel
知道应用程序域的所有内容,Controller
虽然知道Kernel
和Presentation
这两个之间和温和派.更准确地说,这是文件的打开方式:
Presentation
信号FileOpenCommand
.ApplicationController
临危这个信号
ApplicationKernel
创建一个File
对象,ApplicationPresentation
创建一个FilePresentation
对象,FileController
对象,传递File
和FilePresentation
给构造函数.FileController
自身注册为它的观察员File
和FilePresentation
.假设File
提供了一个Init()
不应该阻止用户界面的长时间运行操作.我想到了两种方法:
File::Init()
返回一个封装了一个线程的对象,可用于注册一个被通知进度,错误,完成等的观察者.这FileController
会给(谁将成为观察者)带来很多责任,因为它现在可以从主线程以及工作线程.Controller
.File::Init()
什么都不会返回,但是ApplicationKernel
会在主线程中发出长时间运行操作的信号创建,进度和错误信号.这会拖累很多通信ApplicationKernel
,把它变成类似神对象的东西.这两个中的哪一个是桌面应用程序中多线程的常用方法(如果有的话)?您推荐哪种替代方法?
我建议你考虑使用actor模型。它是一种并发抽象,隐藏了许多与线程、锁等相关的细节。
编辑
@CMR 的评论引发了一些额外的评论......
在参与者模型下,我想应用程序仍将使用问题中建议的相同组件来构建:Presentation
、ApplicationController
等。与参与者模型的区别在于组件(现在的参与者)不会相互直接引用。相反,他们会持有可以相互发布异步、不可变消息的通道。
“打开文件”情况下的事件序列在参与者模型中本质上是相同的,除了通道将被传递到FileController
步骤 2.3 中而不是直接对象引用。同样,观察者注册也是通过渠道进行的。
那么有什么区别呢?主要区别在于没有任何代码需要线程感知。线程对于应用程序逻辑来说是不可见的,这是参与者框架所关心的。如果可以遵循仅通过通道传递不可变对象的规则(某些参与者框架强制执行),那么几乎所有与线程同步相关的困难逻辑都会消失。当然,人们必须将思维方式从同步编程模型转换为异步编程模型——这不一定是一项微不足道的任务。然而,我认为这种切换的成本比不必考虑线程安全(至少在某些复杂的系统中)的好处要多。
特别是在 UI 编程中,异步模型可以更轻松地提供良好的用户反馈。例如,UI 元素可能会启动长时间运行的任务,显示“正在工作...”消息,然后进入睡眠状态。一段时间后,一条消息到达,传递长时间运行的任务的结果,然后 UI 元素将显示该结果,以代替“正在工作...”消息。以类似的方式,当每个树节点的数据以传入消息到达时,可以增量地构建树视图。
您可以将 Actor 模型视为经典 UI“事件泵”方法的概括 - 不同之处在于每个组件(Actor)同时运行自己的事件泵,而不是一个泵分派给一堆组件。Actor 框架提供了一种以非常低的开销运行大量甚至大量此类“同时泵”的方法。特别是,少量线程(例如,每个 cpu 一个)为大量参与者提供服务。