multithreading - 进度条和多线程,解耦 GUI 和逻辑——哪种设计模式最好?

标签 multithreading model-view-controller progress-bar observer-pattern decoupling

我正在寻找适合我的应用程序设计的设计模式。

我的应用程序处理大量数据并生成一些图表。
数据处理(从文件中获取、CPU 密集型计算)和图形操作(绘制、更新)在单独的线程中完成。

图形可以滚动 - 在这种情况下需要处理新的数据部分。
因为一个图上可以有多个系列,所以可以产生多个线程(每个系列两个线程,一个用于数据集更新,一个用于图更新)。

我不想创建多个进度条。相反,我想要一个通知全局进展的单一进度条。目前我可以想到 MVC 和 Observer/Observable,但它有点模糊 :) 也许有人可以指出我正确的方向,谢谢。

最佳答案

我曾经花了一周的大部分时间,试图在一个非常复杂的算法上制作一个平滑的、非打嗝的进度条。

该算法有 6 个不同的步骤。每个步骤都有严重依赖于 A) 正在处理的底层数据的时序特征,不仅是数据的“数量”,还有数据的“类型”,以及 B) 随着 CPU 数量的增加,步骤中的 2 步扩展得非常好, 2 个步骤在 2 个线程中运行,2 个步骤实际上是单线程的。

与内核数量相比,数据混合对每个步骤的执行时间的影响要大得多。

最终破解它的解决方案真的很简单。我创建了 6 个函数来分析数据集并尝试预测每个分析步骤的实际运行时间。每个函数中的启发式都分析了正在分析的数据集和 CPU 的数量。根据我自己的 4 核机器的运行时数据,每个函数基本上都返回了它在我的机器上预期花费的毫秒数。

f1(..) + f2(..) + f3(..) + f4(..) + f5(..) + f6(..) = 以毫秒为单位的总运行时间

现在有了这些信息,您就可以有效地知道每个步骤应该占用的总执行时间的百分比。现在,如果您说 step1 应该占用 40% 的执行时间,您基本上需要找出如何从该算法中发出 40 个 1% 的事件。假设 for 循环正在处理 100,000 个项目,您可能会这样做:

for (int i = 0; i < numItems; i++){
     if (i % (numItems / percentageOfTotalForThisStep) == 0) emitProgressEvent();
     .. do the actual processing ..
}

该算法为我们提供了一个完美无瑕的丝滑进度条。您的实现技术可以在进度条中提供不同形式的缩放和功能,但思考问题的基本方式是相同的。

是的,在我的机器上计算出启发式引用数字并不重要 - 唯一真正的问题是,如果您想在另一台机器上运行时更改数字。但是您仍然知道比率(这是这里唯一真正重要的事情),因此您可以看到本地硬件的运行方式与我拥有的硬件有何不同。

现在普通的 SO 读者可能想知道为什么有人会花一周时间制作一个平滑的进度条。该功能是首席销售员要求的,我相信他在销售 session 中使用它来获得契约(Contract)。有钱能使鬼推磨 ;)

关于multithreading - 进度条和多线程,解耦 GUI 和逻辑——哪种设计模式最好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/549545/

相关文章:

c# - 在 Caliburn.micro 中使用 ProgressBar

c - 在 Linux 上用 C 处理多线程 TCP 服务器的最佳方法

java - 关于多线程开发的好博客?

c++ - 没有 volatile 的互斥锁功能是否足够?

iphone - ViewController 和通知中心( View ,不是设计模式 :p)

javascript - 如何将curl上传进度发送给ajax显示

c++ - 寻找交换两个关联容器的无锁可能性

c# - 关于在 C# MVC 中实现命令模式的问题

javascript - AngularJS Controller 返回表单

android - 更改进度条颜色