多线程对桌面应用程序的体系结构有何影响?

Osw*_*ald 7 language-agnostic architecture multithreading desktop-application

我正在编写一个多线程桌面应用程序.

通常

我不确定多线程对架构的影响.有很多关于架构的文献,但我知道没有考虑多线程的文献.有很多关于多线程(互斥,信号量等)的低级文献的文献,但我知道没有描述这些概念是如何嵌入到架构中的.

您建议哪些文献填补这一空白?

尤其

我的申请包括

  • Presentation 使用GUI工具包创建和管理对话框,
  • Kernel 知道应用程序域的所有内容,
  • Controller虽然知道KernelPresentation这两个之间和温和派.

更准确地说,这是文件的打开方式:

  1. Presentation信号FileOpenCommand.
  2. ApplicationController临危这个信号
    1. 使用ApplicationKernel创建一个File对象,
    2. 使用ApplicationPresentation创建一个FilePresentation对象,
    3. 创建一个FileController对象,传递FileFilePresentation给构造函数.
  3. FileController自身注册为它的观察员FileFilePresentation.

假设File提供了一个Init()不应该阻止用户界面的长时间运行操作.我想到了两种方法:

  1. File::Init()返回一个封装了一个线程的对象,可用于注册一个被通知进度,错误,完成等的观察者.这FileController会给(谁将成为观察者)带来很多责任,因为它现在可以从主线程以及工作线程.
  2. 完全隐藏工作线程Controller.File::Init()什么都不会返回,但是ApplicationKernel会在主线程中发出长时间运行操作的信号创建,进度和错误信号.这会拖累很多通信ApplicationKernel,把它变成类似神对象的东西.

这两个中的哪一个是桌面应用程序中多线程的常用方法(如果有的话)?您推荐哪种替代方法?

WRe*_*ach 3

我建议你考虑使用actor模型。它是一种并发抽象,隐藏了许多与线程、锁等相关的细节。

编辑

@CMR 的评论引发了一些额外的评论......

在参与者模型下,我想应用程序仍将使用问题中建议的相同组件来构建:PresentationApplicationController等。与参与者模型的区别在于组件(现在的参与者)不会相互直接引用。相反,他们会持有可以相互发布异步、不可变消息的通道。

“打开文件”情况下的事件序列在参与者模型中本质上是相同的,除了通道将被传递到FileController步骤 2.3 中而不是直接对象引用。同样,观察者注册也是通过渠道进行的。

那么有什么区别呢?主要区别在于没有任何代码需要线程感知。线程对于应用程序逻辑来说是不可见的,这是参与者框架所关心的。如果可以遵循仅通过通道传递不可变对象的规则(某些参与者框架强制执行),那么几乎所有与线程同步相关的困难逻辑都会消失。当然,人们必须将思维方式从同步编程模型转换为异步编程模型——这不一定是一项微不足道的任务。然而,我认为这种切换的成本比不必考虑线程安全(至少在某些复杂的系统中)的好处要多。

特别是在 UI 编程中,异步模型可以更轻松地提供良好的用户反馈。例如,UI 元素可能会启动长时间运行的任务,显示“正在工作...”消息,然后进入睡眠状态。一段时间后,一条消息到达,传递长时间运行的任务的结果,然后 UI 元素将显示该结果,以代替“正在工作...”消息。以类似的方式,当每个树节点的数据以传入消息到达时,可以增量地构建树视图。

您可以将 Actor 模型视为经典 UI“事件泵”方法的概括 - 不同之处在于每个组件(Actor)同时运行自己的事件泵,而不是一个泵分派给一堆组件。Actor 框架提供了一种以非常低的开销运行大量甚至大量此类“同时泵”的方法。特别是,少量线程(例如,每个 cpu 一个)为大量参与者提供服务。