design-patterns - 設計模式python - 設計模式可復用物件導向軟體的基礎




進度條設計模式? (4)

我正在寫的應用程序執行一個長度算法,通常需要幾分鐘才能完成。 在這段時間內,我想向用戶顯示一個進度條,表示算法的完成程度。

該算法分為幾個步驟,每個步驟都有自己的典型時間。 例如-

  • 初始化(500毫秒)
  • 讀取輸入(5秒)
  • 步驟1(30秒)
  • 第2步(3分鐘)
  • 寫輸出(7秒)
  • 關閉(10毫秒)

每個步驟都可以通過設置其工作範圍(比如[0至150])來輕鬆報告進度,然後在主循環中報告完成的值。

我現在所建立的是一個嵌套進度監視器的方案,它構成了一種隱含的進度報告樹。

所有進度監視器都從一個接口IProgressMonitor繼承:

class IProgressMonitor
{
public:
  void setRange(int from, int to) = 0;
  void setValue(int v) = 0;
};

樹的根是連接到實際GUI界面的ProgressMonitor:

class GUIBarProgressMonitor : public IProgressMonitor
{
   GUIBarProgressMonitor(ProgressBarWidget *);
};

樹中的任何其他節點都是監視器,它們控制父進程的一部分:

class SubProgressMonitor : public IProgressMonitor
{
  SubProgressMonitor(IProgressMonitor *parent, int parentFrom, int parentLength)
  ...
};

SubProgressMonitor控制SubProgressMonitor的範圍[parentFrom, parentFrom+parentLength]

通過這個方案,我能夠根據全球時間中每個步驟的預期相對部分,靜態地劃分頂級進度。 每一步可以進一步細分成片等“

這樣做的主要缺點是分區是靜態的,根據在運行時發現的變量進行更改是很痛苦的。

所以問題是:有沒有已知的進度監控設計模式可以解決這個問題?


佩特是我參與一個大型項目的方法; 在我們的試點和首次推出期間,我們的數千移動設備中的每一個都發回了定時和使用數據,我們使用所花時間的平均值,中位數和標準偏差來微調我們任務的配置(當任務被允許運行,允許運行多長時間,在進度條顯示中使用了什麼值等)。 由於我們的解決方案與您的解決方案有些相似,但是由XML配置文件中提供的值驅動,所以我們考慮將其構建為一個自動化系統(例如,服務器將在一定的時間間隔內檢查這些值,注意某些任務在最近比以前更新的配置文件重新安排或延長他們),但認為這是不值得的麻煩,只是為了防止每隔幾個星期快速人為審查。

因為我不知道你的問題的技術解決方案,所以我認為你向用戶展示的內容(以及你花費多少時間開發一個解決方案)應該基於功能上的關注:誰在使用這個? 信息有多準確? 這是一個互動的過程,在這個過程中,他們不能做其他的工作,或者他們可以讓它在後台運行,並回到它? 工作過程中,您的長時間運行的功能是時間敏感還是關鍵任務?

對不起,我實際上不能給你你正在尋找的答案,但也許想想你想在廣泛的筆觸實現的東西敲開一個好主意。 =)


這是一個棘手的問題,我們在之前的項目中也遇到了困難。

我所能想到的最好的辦法就是統計每個階段在現實生活中實際佔用的時間,並相應地調整相對間隔長度。

我們還沒有在那個項目中實現它(至少和我在那裡一樣),所以這只是一個理論上的想法:-)


您可以考慮用進度圈替換進度欄。 如果任務有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方法)以向用戶顯示進度。





progress-bar