В веб-приложении каждая задача выполняется в виде запроса и ответа.
Программирование на стороне клиента - это HTML-код с Java-скриптом и его фреймворками, библиотеки выполняются в Internet Explorer, Mozilla, Chrome-браузерах. В сценарии Java-сценария серверные сервлеты программирования выполняются в Tomcat, web-логике, j боссе, WebSphere severs
Почему бы и нет?
(linesProcessed / TimeTaken)
(timetaken / linesProcessed) * LinesLeft = TimeLeft
TimeLeft
будет выражаться в любой единице времени timeTaken
.
Спасибо за комментарий, который вы правы, это должно быть:
(TimeTaken / linesProcessed) * linesLeft = timeLeft
, поэтому мы имеем
(10 / 100) * 200
= 20 секунд сейчас 10 секунды идут мимо (20 / 100) * 200
= 40 секунд осталось еще 10 секунд, и мы обрабатываем еще 100 строк (30 / 200) * 100
= 15 секунд, и теперь мы все видим, почему диалог копирования файла перескакивает с 3 часов до 30 минут :-)
Как насчет этого ....
Я использовал это, чтобы пройти через набор записей (строки в файле Excel в одном случае)
L - текущая строка число X - это общее количество строк, для которых dat_Start имеет значение Now (), когда начинается процедура
Debug.Print Format((L / X), "percent") & vbTab & "Time to go:" & vbTab & Format((DateDiff("n", dat_Start, Now) / L) * (X - L), "00") & ":" & Format(((DateDiff("s", dat_Start, Now) / L) * (X - L)) Mod 60, "00")
Как правило, во время обработки вы знаете три вещи:
С учетом этих элементов оценка (если время обработки элемента не будет постоянным) оставшегося времени будет
B * C / A
Не воскрешать мертвый вопрос, но я продолжал возвращаться к ссылке на эту страницу. Вы можете создать метод расширения в классе «Секундомер», чтобы получить функциональные возможности, которые позволят получить ожидаемый оставшийся промежуток времени.
static class StopWatchUtils
{
/// <summary>
/// Gets estimated time on compleation.
/// </summary>
/// <param name="sw"></param>
/// <param name="counter"></param>
/// <param name="counterGoal"></param>
/// <returns></returns>
public static TimeSpan GetEta(this Stopwatch sw, int counter, int counterGoal)
{
/* this is based off of:
* (TimeTaken / linesProcessed) * linesLeft=timeLeft
* so we have
* (10/100) * 200 = 20 Seconds now 10 seconds go past
* (20/100) * 200 = 40 Seconds left now 10 more seconds and we process 100 more lines
* (30/200) * 100 = 15 Seconds and now we all see why the copy file dialog jumps from 3 hours to 30 minutes :-)
*
* pulled from http://stackoverflow.com/questions/473355/calculate-time-remaining/473369#473369
*/
if (counter == 0) return TimeSpan.Zero;
float elapsedMin = ((float)sw.ElapsedMilliseconds / 1000) / 60;
float minLeft = (elapsedMin / counter) * (counterGoal - counter); //see comment a
TimeSpan ret = TimeSpan.FromMinutes(minLeft);
return ret;
}
}
Пример:
int y = 500;
Stopwatch sw = new Stopwatch();
sw.Start();
for(int x = 0 ; x < y ; x++ )
{
//do something
Console.WriteLine("{0} time remaining",sw.GetEta(x,y).ToString());
}
Надеюсь, это будет полезно для кого-то.
EDIT: Следует отметить, что это наиболее точно, когда каждый цикл принимает одинаковое количество времени. Редактирование 2: вместо подкласса я создал метод расширения.
Это действительно зависит от того, что делается ... строк недостаточно, если каждая отдельная строка не принимает одинаковое количество времени.
Лучший способ (если ваши строки не похожи), вероятно, будет чтобы посмотреть на логические разделы кода, узнать, как долго каждый раздел занимает среднее значение, а затем использовать эти средние тайминги для оценки прогресса.
Я сделал это, и он работает неплохо, не стесняйтесь изменять подпись метода в соответствии с вашими типами переменных или также с типом возврата, возможно, вы хотели бы получить объект TimeSpan или только секунды ...
/// <summary>
/// Calculates the eta.
/// </summary>
/// <param name="processStarted">When the process started</param>
/// <param name="totalElements">How many items are being processed</param>
/// <param name="processedElements">How many items are done</param>
/// <returns>A string representing the time left</returns>
private string CalculateEta(DateTime processStarted, int totalElements, int processedElements)
{
int itemsPerSecond = processedElements / (int)(processStarted - DateTime.Now).TotalSeconds;
int secondsRemaining = (totalElements - processedElements) / itemsPerSecond;
return new TimeSpan(0, 0, secondsRemaining).ToString();
}
Вам потребуется инициализировать переменную DateTime
при запуске обработки и отправить ее методу на каждой итерации.
Не забывайте, что, вероятно, ваше окно будет заблокировано, если процесс довольно длинный, поэтому, когда вы помещаете возвращаемое значение в элемент управления, не забудьте использовать его метод .Refresh()
.
Если вы используете потоки, вы можете попытаться установить текст используя метод Invoke(Action)
, было бы легче использовать этот метод расширения для легкого архивирования .
Если вы используете консольное приложение, то вам не должно быть проблем с отображением вывода строка за строкой.
Надеюсь, что это кому-то поможет.
нет стандартного алгоритма, о котором я знаю, мой sugestion был бы следующим:
Вероятно, вы видели программы, в которых load bar работает намного быстрее в одной точке, чем в другой. Ну, это в значительной степени, потому что так они и делают. (хотя они, вероятно, просто помещают инкременты с регулярными интервалами в основную оболочку)
Если вы знаете, что процент завершен, и вы можете просто предположить, что линейная шкала времени линейна, может работать что-то вроде
timeLeft = timeSoFar * (1 / Percentage)
.
Я удивлен, что никто не ответил на этот вопрос кодом!
Простой способ рассчитать время, как ответил @JoshBerke, можно закодировать следующим образом:
DateTime startTime = DateTime.Now;
for (int index = 0, count = lines.Count; index < count; index++) {
// Do the processing
...
// Calculate the time remaining:
TimeSpan timeRemaining = TimeSpan.FromTicks(DateTime.Now.Subtract(startTime).Ticks * (count - (index+1)) / (index+1));
// Display the progress to the user
...
}
Этот простой пример отлично подходит для простого расчета прогресса. Однако, для более сложной задачи есть много способов, чтобы этот расчет мог быть улучшен!
Например, когда вы загружаете большой файл, скорость загрузки может легко меняться. Чтобы вычислить наиболее точный «ETA», хорошим алгоритмом было бы только рассмотрение последних 10 секунд прогресса. Выполните ETACalculator.cs для реализации этого алгоритма!
ETACalculator.cs из Progression - библиотека с открытым исходным кодом, которую я написал. Он определяет очень простую в использовании структуру для всех видов «расчета прогресса». Это позволяет легко вставлять шаги, сообщающие о разных типах прогресса. Если вы обеспокоены восприятием производительности (как предложил @JoshBerke), это очень поможет вам.
Убедитесь, что вы воспринимаете производительность .
Хотя все тестовые бары занимали ровно столько же времени в тесте, две характеристики заставили пользователей думать о процессе был быстрее, даже если это не было:
BLOCKQUOTE>
- индикаторы выполнения, которые плавно продвигались к завершению
- индикаторы выполнения, которые ускорялись к концу
Это сильно зависит от того, что такое «что-то». Если вы можете предположить, что время обработки каждой строки аналогично, вы можете сделать простой расчет:
TimePerLine = Elapsed / LinesProcessed
TotalTime = TimePerLine * TotalLines
TimeRemaining = TotalTime - LinesRemaining * TimePerLine
Существует 2 способа отображения времени
Моя идея / формула более вероятна:
Обработано - обновлено с текущий поток от 0 до Total
У меня есть таймер с интервалом 1000 мс, который вычисляет обрабатываемые в секунду:
processedPerSecond = Processed - lastTickProcessed;
lastTickProcessed = Processed; //store state from past call
обработаноPerSecond и lastTickProcessed - глобальные переменные из метода таймера
Теперь, если мы хотим получить сколько секунд потребуется для завершения обработки (в идеальном постоянном предположении) totalSecondsNeeded = TotalLines / PerSecond
, но мы хотим показать случай 2. TimeLeft так TimeLeftSeconds = (TotalLines - Обработано) / PerSecond
TimeSpan remaining = new TimeSpan(0, 0, (transactions.Count - Processed) / processedPerSecond);
labelTimeRemaining.Text = remaining.ToString(@"hh\:mm\:ss");
Конечно, TimeLeftSeconds будет «прыгать», если PerSecond перепрыгивает, поэтому, если прошлое PerSecond было 10, а затем 30, а затем назад до 10, пользователь увидит его.
Существует способ вычисления среднего значения, но это может не показать в реальном времени, если процесс ускорится в конце
int perSecond = (int)Math.Ceiling((processed / (decimal)timeElapsed.TotalSeconds)); //average not in past second
. Таким образом, разработчик может выбрать «выбрать», метод, который будет наиболее точным, основываясь на предсказании того, насколько «перегружен» процесс обработки
. Мы могли также вычислить и сохранить каждый PerSecond, а затем взять последние 10 секунд и сделать среднее, но в этом случае пользователь будет иметь подождать 10 секунд, чтобы увидеть первый расчет, или мы можем показать время, начиная с первого раза в секунду, а затем постепенно суммировать до 10 последних PerSecond
. Надеюсь, мои «нервные» мысли помогут кому-то построить что-то удовлетворяющее
Где time$("ms")
представляет текущее время в миллисекундах с 00:00 до 00:00, а lof
представляет собой итоговые строки для обработки, а x
представляет текущую строку:
if Ln>0 then
Tn=Tn+time$("ms")-Ln 'grand total of all laps
Rn=Tn*(lof-x)/x^2 'estimated time remaining in seconds
end if
Ln=time$("ms") 'start lap time (current time)
Я уже знал, что процент завершен & amp; время от времени, так что это помогло мне:
TimeElapsed * ((100%%) /% завершено) = TimeRemaining
Затем я обновлял это значение каждый раз, когда% полностью изменилось, постоянный изменяющийся ETA.
Функция PowerShell
function CalculateEta([datetime]$processStarted, [long]$totalElements, [long]$processedElements) {
$itemsPerSecond = $processedElements / [DateTime]::Now.Subtract($processStarted).TotalSeconds
$secondsRemaining = ($totalElements - $processedElements) / $itemsPerSecond
return [TimeSpan]::FromSeconds($secondsRemaining)
}