Design patterns 进度条设计模式?
我正在编写的应用程序执行一个长度算法,通常需要几分钟才能完成。在这段时间里,我想向用户展示一个进度条,它尽可能精确地指示完成了多少算法 该算法分为几个步骤,每个步骤都有自己的典型定时。例如—Design patterns 进度条设计模式?,design-patterns,oop,progress-bar,Design Patterns,Oop,Progress Bar,我正在编写的应用程序执行一个长度算法,通常需要几分钟才能完成。在这段时间里,我想向用户展示一个进度条,它尽可能精确地指示完成了多少算法 该算法分为几个步骤,每个步骤都有自己的典型定时。例如— 初始化(500毫秒) 读取输入(5秒) 步骤1(30秒) 步骤2(3分钟) 写入输出(7秒) 关闭(10毫秒) 通过设置其工作范围(例如[0到150]),然后在主循环中报告完成的值,每个步骤都可以非常轻松地报告其进度 我目前设置的是一个嵌套进度监视器的方案,它形成了一种隐式的进度报告树 所有进度监视器都
- 初始化(500毫秒)
- 读取输入(5秒)
- 步骤1(30秒)
- 步骤2(3分钟)
- 写入输出(7秒)
- 关闭(10毫秒)
IProgressMonitor
:
class IProgressMonitor
{
public:
void setRange(int from, int to) = 0;
void setValue(int v) = 0;
};
树的根是ProgressMonitor,它连接到实际的GUI界面:
class GUIBarProgressMonitor : public IProgressMonitor
{
GUIBarProgressMonitor(ProgressBarWidget *);
};
树中的任何其他节点都是监控器,用于控制父进程的一部分:
class SubProgressMonitor : public IProgressMonitor
{
SubProgressMonitor(IProgressMonitor *parent, int parentFrom, int parentLength)
...
};
subgressMonitor
控制其父级的范围[parentFrom,parentFrom+parentLength]
有了这个方案,我能够根据全局计时中每个步骤的预期相对部分静态划分顶级进度。然后,每个步骤可进一步细分为多个部分等'
这样做的主要缺点是划分是静态的,根据在运行时发现的变量进行更改会很痛苦
因此,问题是:是否有任何已知的进度监控设计模式可以解决这个问题?这是一个棘手的问题,我们在以前的项目中也遇到过这个问题 我能想到的最好办法是收集真实生活中每个阶段实际需要多长时间的统计数据,并相应地调整相对间隔长度
我们还没有在那个项目中实现它(至少在我在那里的时候),所以这只是一个理论上的想法:-)péter是我在一个大型项目中采用的方法;在我们的试点和初始推出期间,我们的数千台移动设备中的每一台都在发回时间和使用数据,我们使用所用时间的平均值、中值和标准差来微调任务的配置(任务允许运行的时间、允许运行的时间、进度条显示中使用的值等)。由于我们的解决方案与您的解决方案有点类似,但由XML配置文件中提供的值驱动,因此我们考虑将其构建为一个自动化系统(例如,服务器会每隔一段时间检查这些值,注意到最近几天某些任务比以前花费的时间更长,并更新配置文件以重新安排或延长时间),但认为仅仅为了防止每隔几周进行一次快速的人工检查并不值得这么麻烦 由于我不知道您的问题的技术解决方案,我认为您向用户展示了什么(以及您花了多少时间开发一个解决方案)应基于功能考虑:谁在使用此功能?信息需要有多准确?这是一个互动过程,在此过程中,他们不能做其他工作,还是可以让它在后台运行并返回到它?您的长期运行功能发生的工作过程是一个时间敏感的或任务关键的过程
很抱歉,我不能给你你想要的答案,但也许思考一下你试图在大范围内实现的目标会让你失去一个好主意。=)一个非常有趣的方法是用户感知 发表了一篇关于用户如何根据进度条报告的进度感知时间流逝的论文(尽管在所有实验中实际持续时间显然是相同的) 请注意,首选的显示公式是(x+(1-x)/2)8,其中
x
是0到1刻度上的实际进度:)
因此,我建议:
- 收集有关给定任务所用时间百分比的统计信息
- 测量初始化并使用它在进度条上缩放进度,保持悲观(例如准备10-15%的缓冲区)
- 就在最后一项任务之前(或最后几项任务,只要它们具有确定的持续时间),全力以赴,以便及时完成进度条(具有渐进加速)
我知道,这是不准确的,但如果用户认为它更快,我会接受它 > P>您可以考虑用进度循环替换进度条。如果任务有N个步骤,则在饼图中创建N个楔子,并在该步骤运行时像进度条一样填充每个楔子
作为一个附加步骤,可能会为每个步骤显示一些文本,以便在步骤进行时可以阅读这些文本。构建一个AggregateProgressMonitor,该监视器根据子进度监视器报告的信息自动计算子进度分段。子进程监视器应至少通知父进程“预期”运行时间。然后,子监控器的估计运行时间可以根据运行时参数通过各自的操作进行更新,并且总体进度报告将相应地自动调整 像这样的
class IAggregateProgressMonitor : public IProgressMonitor
{
void setChildValue(IProgressMonitor *, int v);
void setChildEstimatedTime(IProgressMonitor *, int v);
}
class AggregateProgressMonitor : public IAggregateProgressMonitor
{
void setChildValue(IProgressMonitor * child, int v)
{
int aggregateValue = mapChildValueToAggregateValue(child, v);
setValue(aggregateValue);
}
void setChildEstimatedTime(IProgressMonitor * child, ulong ms)
{
children[child]->estimatedTime = ms;
updateChildProgressRatios();
}
}
class SubProgressMonitor : public IProgressMonitor
{
SubProgressMonitor(IAggregateProgressMonitor *parent, int parentFrom,
int parentLength) ... ;
void setValue(int v)
{
parent->setChildValue(this, v);
}
void setEstimatedRunningTime(ulong ms)
{
parent->setChildEstimatedTime(this, ms);
}
};
您甚至可以使用第一步的观察时间来重新映射后续的进度报告器,使其更加准确
您需要在AggregateProgressMonitor中保留某种类型的有序映射,以便能够跟踪和计算来自子对象的所有信息
完成后,您可以扩展AggregateProgressMonitor(覆盖IProgressMonitor方法)以向用户显示进度。否决,因为答案侧重于可视化,但问题是关于代码中的设计模式。行动计划显然远远超出了预期