MadBoy
MadBoy

Reputation: 11114

How to estimate end time of method in WinForms to properly inform user about predicted time of finish?

I've got some timers that measure the time to execute code.

 DateTime startTimeFunctionTotal = DateTime.Now;
     for (int i = 0; i < array.Count; i++) {
         DateTime startTimeFunction = DateTime.Now;
         //some code here

          DateTime stopTimeFunction = DateTime.Now;
          TimeSpan durationTimeFunction = stopTimeFunction - startTimeFunction ;

 }
 DateTime stopTimeFunctionTotal = DateTime.Now;
 TimeSpan durationTimeFunctionTotal = stopTimeFunctionTotal - startTimeFunctionTotal ;

It's allowed (even better) if the predicted time changes according to more data (every loop there is more data so prediction should be more accurate).

I would like to give user a predicted time of finish (both time like 15 minutes, and 10:56).

Upvotes: 5

Views: 970

Answers (3)

Yuriy Faktorovich
Yuriy Faktorovich

Reputation: 68737

Assuming each action in your for statement takes roughly the same amount of time:

List<TimeSpan> timeSpans = new List<TimeSpan>();
for(int i = 0; i < array.Count; i++)
{
    Stopwatch watch = Stopwatch.StartNew();
    //do stuff
    timeSpans.Add(watch.Elapsed);
    long ticksLeft = timeSpans.Sum(ts => ts.Ticks) * (array.Count - i) / timeSpans.Count;
    Console.WriteLine("Left: " + new TimeSpan(ticksLeft));
    Console.WriteLine("Finished in: " + 
        DateTime.Now.AddTicks(ticksLeft));
}

To go with the median use:

long ticksLeft = timeSpans.OrderBy(ts => ts.Ticks)
    .ElementAt(timeSpans.Count / 2).Ticks * (array.Count - i);

Upvotes: 3

Hans Passant
Hans Passant

Reputation: 942307

You can make an auto-correcting guess, as long as there are sufficient operations that each can be timed individually and each take roughly the same amount of time. Start out with a guess and multiply by the number of operations to perform. Measure the time of the next operation and add that to a list. Make a new guess by taking the average of the times in this list and multiply that by the number of operations left.

Your guess will get more accurate as you get more timing samples. And your progress bar will always reach 100% (+/- a wee bit). Taking the median instead of the average is better, it eliminates outliers due to sudden activity on your machine by other processes. And you'll want to throw out old measurements in the list, keeping only 10 to 20 is enough. Keep more samples if the operation time is more variable.

Upvotes: 2

Codesleuth
Codesleuth

Reputation: 10541

To get a better representation of timing for code performance (in a nice TimeSpan) have a look at the System.Diagnostics.StopWatch.

It works like you would expect: Start() to begin timing, Stop() to stop. Read Elapsed to get a TimeSpan of the time taken, or ElapsedTicks for the most accurate measurement (a TimeSpan.Ticks = 1.0 x 10-9 sec, or 100 nano-sec; ElapsedTicks is variable and is relative to the StopWatch.Frequency of 1-sec/value).

Upvotes: 1

Related Questions