System.Timers.Timer How to get the time remaining until Elapse
Asked Answered
P

3

24

Using C#, how may I get the time remaining (before the elapse event will occur) from a System.Timers.Timer object?

In other words, let say I set the timer interval to 6 hours, but 3 hours later, I want to know how much time is remaining. How would I get the timer object to reveal this time remaining?

Portugal answered 17/2, 2010 at 5:29 Comment(0)
R
39

The built-in timer doesn't provide the time remaining until elapse. You'll need to create your own class which wraps a timer and exposes this info.

Something like this should work.

public class TimerPlus : IDisposable
{
    private readonly TimerCallback _realCallback;
    private readonly Timer _timer;
    private TimeSpan _period;
    private DateTime _next;

    public TimerPlus(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period)
    {
        _timer = new Timer(Callback, state, dueTime, period);
        _realCallback = callback;
        _period = period;
        _next = DateTime.Now.Add(dueTime);
    }

    private void Callback(object state)
    {
        _next = DateTime.Now.Add(_period);
        _realCallback(state);
    }

    public TimeSpan Period => _period;
    public DateTime Next => _next;
    public TimeSpan DueTime => _next - DateTime.Now;

    public bool Change(TimeSpan dueTime, TimeSpan period)
    {
        _period = period;
        _next = DateTime.Now.Add(dueTime);
        return _timer.Change(dueTime, period);
    }

    public void Dispose() => _timer.Dispose();
}
Residuary answered 17/2, 2010 at 5:35 Comment(6)
Above and beyond the call, but checked you for your efforts. Thanks, you are very kind. I already have a method that will calculate how much time should be remaining, but wanted to confirm it with output from the actual timer object itself. To bad it isn't inherently provided.Portugal
Yeah, he wrote that fast too. Impressive.Portugal
Samuel, could you provide the usage of this class? I am unsure how to pass in the parameters to your constructor.Semite
@HeseinBurg TimerPlus is a drop-in replacement for Timer (meaning you can use TimerPlus as-is wherever you use Timer). It has the same functionality and API. The addition is the Next property which will always return the DateTime that it will next be triggered.Residuary
Wouldn't this result in a bug in case the user would change the system time while the timer is running?Portent
@Portent Yes. The timer will not actually fire at the wrong time but Next and DueTime will both be wrong until the next timer tick.Residuary
L
23

I am aware, that the topic is more than 3 years old. However I came across it while tackling exactly the same problem.

Inspired by Samuel Neff, I came up with a WinForms-less solution by extending the standard System.Timers.Timer class:

public class TimerPlus : System.Timers.Timer
{
    private DateTime m_dueTime;

    public TimerPlus() : base() => this.Elapsed += this.ElapsedAction;

    protected new void Dispose()
    {
        this.Elapsed -= this.ElapsedAction;
        base.Dispose();
    }

    public double TimeLeft => (this.m_dueTime - DateTime.Now).TotalMilliseconds;
    public new void Start()
    {
        this.m_dueTime = DateTime.Now.AddMilliseconds(this.Interval);
        base.Start();
    }

    private void ElapsedAction(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (this.AutoReset)
            this.m_dueTime = DateTime.Now.AddMilliseconds(this.Interval);
    }
}

I hope it helps.

Logos answered 15/10, 2013 at 13:26 Comment(0)
P
19

I guess the best method is to hold the start time in a variable and then calculate the elapsed time as

TimeSpan t = DateTime.Now - StartTime;
Pavia answered 17/2, 2010 at 5:36 Comment(1)
I agree. But, had to check Sam for his efforts; he wrote a class to help me. Super kind. Thank you both.Portugal

© 2022 - 2024 — McMap. All rights reserved.