如何设置计时器间隔?

时间:2020-05-22 12:56:56

标签: c# winforms

因此,我试图设置倒数计时器间隔,以使1hr = 10分钟(实时),1min = 10秒(实时)和1s = 0.17s(实时)对测试我的代码有帮助。我似乎找不到要更改的代码的一部分而不会引起错误。所以我尝试在初始化组件部分中定义间隔,并收到以下信息:

System.NullReferenceException:“对象引用未设置为对象的实例。”计时器为空。

    private void button1_Click(object sender, EventArgs e)
    {
        AddTimeToClock(TimeSpan.FromSeconds(10));
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        timer = new System.Windows.Forms.Timer();
        timer.Interval = (int)TimeSpan.FromSeconds(1).TotalMilliseconds;
        timer.Tick += OnTimeEvent;
        DisplayTime();
    }
    private void DisplayTime()
    {
        lblTime.Text = countdownClock.ToString(@"hh\:mm\:ss");
    }
    private void OnTimeEvent(object sender, EventArgs e)
    {
        // Subtract whatever our interval is from the countdownClock
        countdownClock = countdownClock.Subtract(TimeSpan.FromMilliseconds(timer.Interval));

        if (countdownClock.TotalMilliseconds <= 0)
        {
            // Countdown clock has run out, so set it to zero 
            // (in case it's negative), and stop our timer
            countdownClock = TimeSpan.Zero;
            timer.Stop();
        }

        // Display the current time
        DisplayTime();
    }
    private void AddTimeToClock(TimeSpan timeToAdd)
    {
        // Add time to our clock
        countdownClock += timeToAdd;

        // Display the new time
        DisplayTime();

        // Start the timer if it's stopped
        //if (!timer.Enabled) timer.Start();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        AddTimeToClock(TimeSpan.FromMinutes(1));
    }

    private void button3_Click(object sender, EventArgs e)
    {
        AddTimeToClock(TimeSpan.FromMinutes(10));
    }

    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBox1.Checked) timer.Start();
        else
        {
            timer.Stop();
        }
    }

2 个答案:

答案 0 :(得分:0)

我建议您为计时器介绍一个包装器。这样一来,您可以公开根据需要缩放的间隔方法。例如:

public class ScaledTimer : IDisposable
{
    private Timer timer;

    public ScaledTimer() => this.timer = new Timer();
    public void Dispose() => timer.Dispose();
    public void Start() => timer.Start();
    public void Stop() => timer.Stop();
    public double Scale { get; set; } = 1;
    public bool Enabled
    {
        get => timer.Enabled;
        set => timer.Enabled = value;
    }

    public int Interval
    {
        get => (int)(timer.Interval * Scale);
        set => timer.Interval = (int)(value / Scale);
    }

    public event EventHandler Tick
    {
        add => timer.Tick += value;
        remove => timer.Tick -= value;
    }
}

将“刻度”设置为10,以使计时器的滴答速度快10倍。请注意,如果您还使用DateTime.Now,这将无法正常工作,因为这将使用实际的系统时间。提取计时器的接口也是一个好主意。这在单元测试时非常有用,因为它可以模拟计时器。计时器的分辨率也很有限,因此如果间隔降低到约16ms,它可能无法很好地工作。

答案 1 :(得分:0)

如果我了解您要完成的任务(以相同的速度计时,但在逻辑上以6倍的速度耗尽countdownClock),那么我认为最好的行动计划是为时间刻度添加一个常数。 / p>

private static readonly int timeScale = 6

然后,当您在OnTimeEvent中调整倒计时时钟时,可以乘以比例。

countdownClock = countdownClock.Subtract(timeScale * TimeSpan.FromMilliseconds(timer.Interval));

将timeScale设置为1以正常速度运行,或将其设置为较高的值以更快地运行。

这将大致说明如何实现目标,但是在调试时需要手工编辑timeScale值才能获得所需的行为。在这里,您可以决定如何最好地管理它-也许您想从配置文件中加载timeScale,或者根据是否定义了#DEBUG进行调整。您可能还想制作一个具有Scale属性的countdownClock类,以进一步封装此行为。最终实施取决于您。