2011-07-26 54 views
0

用什麼算法來計算函數調用的進度?用於報告異步函數調用進度的算法

顯然它很容易,如果你有一個循環做的,是這樣的:

Action<Double> notifier = d => Console.WriteLine("Completed: " + d.ToString()); 

Double _interval = 0.05; 

for (int i = 0; i < 1000; i++) 
      { 
       int rem = default(int); 

       Math.DivRem(i, _interval, out rem); 

       if (rem == 0) 
       { 
        double progress = (double)i/1000; 
        notifier(progress); 
       } 
      } 

可是你知道,當你只是有一些通用的委託,你想異步運行,但也通知的另一個線程它的進步,你不能保證你可以直接使用for循環?其他一些簡單的方法可能是:

1)時間的函數第一(很業績但如果它是一個長期運行的任務)

2)店鋪過去在日誌功能的時機不好,並使用(但這並不一定會考慮額外的變量 - 在任務的特定時間的CPU,內存等)

但是,是否存在更高級的算法,即使只是爲了近似進度?

+0

如果你可以存儲過去的時間,那是最好的辦法。 CPU和內存是你可能會忍受的限制。過去的時機是未來表現的最好指標 –

回答

2

BackgroundWorker類有一個更新回調,但在回答你的問題的'通用算法'尋找完成,不是真的。您可以得到的最接近的是基於函數長度(http://www.ndepend.com/)的估計,這將使您獲得代碼行的長度。

+0

這很有趣,看着代碼行。我想知道,如果您嘗試沿着元數據樹行走並測量涉及的基本操作總數,您是否可以使用基於反射的方法,然後基於此計算估計值。 –

+0

這可以使用NDepend或程序數據庫(pdb)完成。其中最難的部分是獲取程序堆棧指針,以便知道它當前在代碼中的位置......我認爲C#抽象出大部分 –

1

將工作函數傳遞給回調委託並讓它將其進度報告回UI。

UI不應該負責「搞清楚該做什麼」,而應該只是從工作人員那裏進行更新。

例如:

void longRunningFunction(Action<int> updateCallback) 
{ 
     // Do something long, but on measurable places, call updateCallback 
     updateCallback(50); 
} 

並在UI:

longRunningFunction(x => progressBar.SetProgress(x)); 
+0

我很確定這也是我過去所做的。 –

+0

我的問題更多地針對的情況是,無論出於什麼原因,您都無法將updateCallback()寫入函數,而是使用一個通用的Func或Action來推斷其運行進度。例如,假設你有某種文件IO功能 - 你可以用一個非常小的文件運行它,計算它的時間,並用這個時間來估計一個更長的文件需要多長時間。 –

1

這是一個學術問題?

如果沒有,你可以選擇使用BackgroundWorker,它有一個內置的ReportProgress方法

http://msdn.microsoft.com/en-us/library/ka89zff4.aspx

我想你也可以使用.NET反射來看看它的實現,如果你很好奇

+0

即使您沒有在函數中編寫任何類型的時間/進度報告,ReportProgress方法是否可以計算百分比完整數字?如果是這樣的話,我真的會對如何運作感興趣,是的。 –

+0

其實不,不是。所以不是你想要的 –