如何以Windows窗体立即启动计时器?

时间:2018-05-29 20:20:53

标签: c# winforms visual-studio

我有点问题。有象棋计时器之类的东西。当我按下按钮时,当前计时器停止并且第二次启动,但是在1秒之后。我怎样才能立即开始第二个? here is form image

using System;
using System.Windows.Forms;

namespace WindowsFormsApp1 {
    public partial class Form1 : Form {
        byte sec1;
        byte sec2;
        public Form1() {
            InitializeComponent();
            sec1 = 0;
            sec2 = 0;
        }

        private void button1_Click(object sender , EventArgs e) {
            timer1.Start();
            timer2.Stop();
        }
        private void button2_Click(object sender , EventArgs e) {
            timer2.Start();
            timer1.Stop();
        }

        private void timer1_Tick(object sender , EventArgs e) {
            label1.Text = sec1.ToString();
            sec1++;
        }

        private void timer2_Tick(object sender , EventArgs e) {
            label2.Text = sec2.ToString();
            sec2++;
        }

    }
}

2 个答案:

答案 0 :(得分:4)

修改
我知道您的问题是“如何立即启动计时器”,但在您的代码中,它们会立即启动。当你打电话开始时,计时器启动。我相信你看到的效果与嘀嗒事件相关的延迟有关,从我假设的描述设置为1秒间隔。既然你已经说过你正在尝试模拟类似于国际象棋计时器的东西(虽然在你的情况下计数而不是向下),那么使用类似秒表的东西可以启动,停止并显示经过的时间将是一个更接近的模型。由于有一个Stopwatch类可以提供这种行为,我认为使用其中的两个更容易实现它,只需要一个后台线程就可以根据需要频繁更新UI。您甚至可以在每个按钮按钮中添加更新调用,以确保文本框是最新的。

===============================

也许你应该使用Stopwatch类的两个实例代替计时器。这将消除您用于跟踪秒数的两个变量的需要,因为秒表类将保留每个计数器的已用时间。

然后在你的按钮方法中你可以这样做:

private Stopwatch sw1 = new Stopwatch();
private Stopwatch sw2 = new Stopwatch();

    private void button1_Click(object sender , EventArgs e) {
        sw1.Start();
        sw2.Stop();
    }
    private void button2_Click(object sender , EventArgs e) {
        sw2.Start();
        sw1.Stop();
    }

然后你可以使用一个后台工作程序或一些其他后台线程来运行和更新你的文本框,其中包含你需要获取经过时间的计时器所用的时间。

// This will give you the total number of seconds elapsed.
var timer1Seconds = Math.Floor(sw1.Elapsed.TotalSeconds);

以下是如何更新UI的示例:

    private bool _stop = false;
    public Form1()
    {
        InitializeComponent();

        Task.Run(() =>
        {
            while(!_stop)
            {
                UpdateElapsedTimes();
                Thread.Sleep(1000);
            }
        }
    }

    private void UpdateElapsedTimes()
    {
        if (InvokeRequired)
        {
            Invoke(UpdateElapsedTimes());
            return;
        }

        label1.Text = Math.Floor(sw1.Elapsed.TotalSeconds).ToString();
        label2.Text = Math.Floor(sw2.Elapsed.TotalSeconds).ToString();
    }

注意 - 在生产程序中我不会使用布尔值作为我的循环检查器,你会使用事件句柄,如果你想允许暂停更新,可能还有几个事件句柄,这只是为了显示一个想法怎么做您可以直接从线程方法调用并删除InvokeRequired检查,但我添加了它以获得额外的安全性,因为它在那里我在循环中跳过它。

答案 1 :(得分:0)

计时器立即启动。问题是你没有报告几秒的分数,所以显示将显示0,直到经过一整秒,这在技术上是准确的。

如果您想立即显示1,只需按此方式初始化变量。

public Form1() {
    InitializeComponent();
    sec1 = 1;
    sec2 = 1;
}