System.Timers.Timer如何获取剩余时间直到Elapse

23
使用C#,我如何从System.Timers.Timer对象中获取剩余时间(在逾期事件发生之前)?
换句话说,假设我将计时器间隔设置为6小时,但是3小时后,我想知道还剩多少时间。我该如何让计时器对象显示这个剩余时间?
3个回答

38

内置计时器不提供到期前剩余的时间。您需要创建自己的类,将计时器封装并公开此信息。

像这样的东西应该可以工作:

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();
}

超出了要求,但感谢你的努力。谢谢你,你非常友善。我已经有一个可以计算剩余时间的方法,但想要通过实际计时器对象的输出来确认它。很遗憾它不是固有提供的。 - Lonnie Best
3
是的,他写得很快。令人印象深刻。 - Lonnie Best
1
Samuel,你能提供一下这个类的用法吗?我不确定如何将参数传递给你的构造函数。 - Hesein Burg
1
@HeseinBurg 的 TimerPlusTimer 的即插即用替代品(这意味着您可以在任何使用 Timer 的地方直接使用 TimerPlus)。它具有相同的功能和 API。新增的是 Next 属性,它将始终返回下一次触发的 DateTime - Samuel Neff
1
如果用户在计时器运行时更改系统时间,这是否会导致错误? - Tohnmeister
1
@Tohnmeister 是的。计时器实际上不会在错误的时间触发,但是NextDueTime在下一个计时器滴答之前都会是错误的。 - Samuel Neff

22

我知道这个话题已经超过3年了,但是在解决完全相同的问题时,我偶然发现了它。

受 Samuel Neff 的启发,我通过扩展标准的 System.Timers.Timer 类提出了一个没有 WinForms 的解决方案:

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);
    }
}

希望它有所帮助。


17

我想最好的方法是将开始时间保存在一个变量中,然后计算经过的时间为

TimeSpan t = DateTime.Now - StartTime;

2
我同意。但是,我必须检查一下Sam的努力;他写了一个类来帮助我。非常友善。谢谢你们俩。 - Lonnie Best

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接