public void Update(string message, long processedItems, long totalItems) { var secondsSinceLastAverage = (DateTime.Now - _lastProgressEvent.Key).TotalSeconds; if (secondsSinceLastAverage > 2) { if (_lastProgressEvent.Key != DateTime.MinValue) { var itemsSinceLastProgress = processedItems - _lastProgressEvent.Value; var itemsPerSecond = itemsSinceLastProgress / secondsSinceLastAverage; _perSecondAverages.Add(itemsPerSecond); if (_perSecondAverages.Count() > 20) { _perSecondAverages.RemoveAt(0); } } _lastProgressEvent = new KeyValuePair <DateTime, double>(DateTime.Now, processedItems); } var itemsRemaining = totalItems - processedItems; var timeEstimate = _perSecondAverages.Count() < 1 ? "Estimating time left" : string.Format("{0} left", TimeSpan .FromSeconds(itemsRemaining / WeightedAverage(_perSecondAverages)) .GetHumanized()); var percentDone = (processedItems * 100) / totalItems; lock (_lock) { ConsoleProgressBar.Render(percentDone, string.Format("{0} ({1}% of {2:0.0} {3}). {4}", message, percentDone, _displayUnitConversion(totalItems), _displayUnit, timeEstimate)); } }