Как оценить время окончания метода в WinForms, чтобы правильно проинформировать пользователя о предполагаемом времени окончания? - PullRequest
5 голосов
/ 01 марта 2010

У меня есть несколько таймеров, которые измеряют время выполнения кода.

 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 ;

Допускается (даже лучше), если прогнозируемое время изменяется в соответствии с большим количеством данных (каждый цикл содержит больше данных, поэтому прогноз должен быть более точным).

Я бы хотел дать пользователю прогнозируемое время финиша (как 15 минут, так и 10:56).

Ответы [ 3 ]

3 голосов
/ 01 марта 2010

Предполагается, что каждое действие в вашем операторе for занимает примерно одинаковое количество времени:

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));
}

Для медианного использования:

long ticksLeft = timeSpans.OrderBy(ts => ts.Ticks)
    .ElementAt(timeSpans.Count / 2).Ticks * (array.Count - i);
2 голосов
/ 01 марта 2010

Вы можете сделать предположение с автокоррекцией, если есть достаточно операций, каждая из которых может быть рассчитана по отдельности и каждая из которых занимает примерно одинаковое количество времени. Начните с предположения и умножьте на количество операций, которые нужно выполнить. Измерьте время следующей операции и добавьте это в список. Сделайте новое предположение, взяв среднее время в этом списке и умножьте его на количество оставшихся операций.

Ваше предположение будет более точным по мере того, как вы будете получать больше временных выборок. И ваш индикатор прогресса всегда будет достигать 100% (+/- крошечный бит). Лучше брать медиану вместо среднего, это исключает выбросы из-за внезапной активности вашей машины другими процессами. И вы захотите выбросить старые измерения в список, достаточно лишь от 10 до 20. Оставьте больше образцов, если время операции более изменчиво.

1 голос
/ 01 марта 2010

Чтобы получить лучшее представление о времени выполнения кода (в хорошем TimeSpan), взгляните на System.Diagnostics.StopWatch.

Это работает так, как вы ожидаете: Start() для начала отсчета времени, Stop() для остановки. Прочитайте Elapsed, чтобы получить TimeSpan отведенного времени или ElapsedTicks для наиболее точного измерения (a TimeSpan.Ticks = 1,0 x 10 -9 сек или 100 нано-секунд; ElapsedTicks является переменной величиной и относится к StopWatch.Frequency из 1 с / значение).

...