Skip to main content

Offers common timeout support. The source was extracted from the System.Threading.ReaderWriterLockSlim class.

public struct TimeoutTracker
{
    private readonly int _total;
    private readonly int _start;

    public bool IsExpired
    {
        get
        {
            return RemainingMilliseconds == 0;
        }
    }

    public int RemainingMilliseconds
    {
        get
        {
            if (_total == -1 || _total == 0)
            {
                return _total;
            }

            int tickCount = Environment.TickCount - _start;
            if (tickCount < 0 || tickCount >= _total)
            {
                return 0;
            }

            return _total - tickCount;
        }
    }

    public TimeoutTracker(TimeSpan timeout)
    {
        long totalMilliseconds = (long)timeout.TotalMilliseconds;
        if (totalMilliseconds < -1 || totalMilliseconds > 2147483647)
        {
            throw new ArgumentOutOfRangeException("timeout");
        }

        _total = (int)totalMilliseconds;
        if (_total != -1 && _total != 0)
        {
            _start = Environment.TickCount;
            return;
        }

        _start = 0;
    }

    public TimeoutTracker(int millisecondsTimeout)
    {
        if (millisecondsTimeout < -1)
        {
            throw new ArgumentOutOfRangeException("millisecondsTimeout");
        }

        _total = millisecondsTimeout;
        if (_total != -1 && _total != 0)
        {
            _start = Environment.TickCount;
            return;
        }

        _start = 0;
    }
}

// =================================================================
// Usage:
// =================================================================

void Main()
{
    var tt = new TimeoutTracker(1000);

    Thread.Sleep(500);

    if (tt.IsExpired)
    {
        Console.WriteLine("Timeout expired.");
    }
    else
    {
        Console.WriteLine("Still ticking with \"{0}\" milli-seconds left on the clock...",
            tt.RemainingMilliseconds);
    }

    Thread.Sleep(500);

    if (tt.IsExpired)
    {
        Console.WriteLine("Timeout expired.");
    }
    else
    {
        Console.WriteLine("Still ticking with \"{0}\" milli-seconds left on the clock...",
            tt.RemainingMilliseconds);
    }
}