2011-07-26 96 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

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