Progress timer

I know - it's been too long since my last post and i feel ashamed. So here goes.

I have put together a neat progress timer class for such occasions when you have a long running process looping over a bunch of items and doing its thing. The timer keeps track of the recent times and remaining time. Enough of the chit-chat - to the code...

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

public class ProgressTimer
{
 private readonly Queue _timeQueue;
 private int _itemsRemaining;
 private int _limit;
 private Stopwatch _stopWatch;

 public ProgressTimer(int historyLimit)
 {
  if(historyLimit <= 0)
   throw new ArgumentOutOfRangeException("historyLimit", "History limit must be greater than 0.");

  _timeQueue = new Queue();
  _stopWatch = new Stopwatch();
  _itemsRemaining = 0;
  _limit = historyLimit;
 }

 public void Initialize(int totalItems)
 {
  _itemsRemaining = totalItems;
  _timeQueue.Clear();
  
  if(_stopWatch.IsRunning)
   _stopWatch.Stop();

  _stopWatch.Reset();
 }

 public void BeginStep()
 {
  ThrowIfStopWatchRunning();

  _itemsRemaining--;
  _stopWatch.Reset();
  _stopWatch.Start();
 }

 public void EndStep()
 {
  _stopWatch.Stop();
  if (_timeQueue.Count >= _limit)
  {
   _timeQueue.Dequeue();
  }

  _timeQueue.Enqueue(TimeSpan.FromMilliseconds(_stopWatch.ElapsedMilliseconds));
 }

 public TimeSpan StepTime
 {
  get
  {
   ThrowIfStopWatchRunning();

   return TimeSpan.FromMilliseconds(_stopWatch.ElapsedMilliseconds);
  }
 }

 public TimeSpan RemainingTime
 {
  get
  {
   ThrowIfStopWatchRunning();

   if (_itemsRemaining <= 0)
    return new TimeSpan(0);

   var averageTimeMilliseconds = _timeQueue.Average(x => x.TotalMilliseconds);
   var totalRemainingMilliseconds = _itemsRemaining * averageTimeMilliseconds;
   return TimeSpan.FromMilliseconds(totalRemainingMilliseconds);
  }
 }

 public int QueuedTimesCount
 {
  get
  {
   return _timeQueue.Count;
  }
 }

 public int ItemsRemaining
 {
  get
  {
   return _itemsRemaining;
  }
 }

 private void ThrowIfStopWatchRunning()
 {
  if (_stopWatch.IsRunning)
   throw new InvalidOperationException("The step is still in progress. End the step by calling EndStep().");
 }
}

And here's a sample of how to put it all to good use...

var timer = new ProgressTimer(2);
timer.Initialize(2);

timer.BeginStep();
// As if real work is happening
Thread.Sleep(3000);
timer.EndStep();

var stepTime = timer.StepTime;
var remainingTime = timer.RemainingTime;

timer.BeginStep();
// As if real work is happening
Thread.Sleep(2000);
timer.EndStep();

stepTime = timer.StepTime;
remainingTime = timer.RemainingTime;

I hope someone out there benefits from this. And as always I'm open for comments to improve the above piece of code.

Peace,
Mihkel