C# 在 Windows 应用商店应用中重置倒数计时器 - 调度程序计时器

本文关键字:计时器 应用 倒数 调度程序 Windows | 更新日期: 2023-09-27 18:34:40

我是general_编程的C#newbie_and,Ι正在尝试构建一个带有倒数计时器的数学测验应用程序。

每次用户单击开始按钮时,我都会生成一个方程式,并给他最多 60 秒的回答时间。用户回答 - 无论他的答案是错还是对,都不会matter_,他/她可以再次单击新方程式。因此,我希望每次向用户显示新的随机方程时,计时器都会重置。到目前为止,我只设法在 60 秒的时间跨度过去时重置它,但即使这样也无法正常工作,有时它会显示 59 或 58 秒而不是 60 秒。

到目前为止,阅读其他问题对我没有多大帮助,计时器让我感到困惑。我也接受使我的代码更简单、更优雅的建议。

这是我的代码:

EquationView.xaml.cs

public sealed partial class EquationView : Page
    {
        DispatcherTimer timer = new DispatcherTimer();
        int tick = 60;
        int result;
        public EquationView()
        {
            this.NavigationCacheMode = NavigationCacheMode.Enabled;
            this.InitializeComponent();
        }
        private void startButton_Click(object sender, RoutedEventArgs e)
        {
            // Once clicked then disabled
            startButton.IsEnabled = false;
            // Enable buttons required for answering 
            resultTextBox.IsEnabled = true;
            submitButton.IsEnabled = true;
            var viewModel = App.equation.GenerateEquation();
            this.DataContext = viewModel;
            result = App.equation.GetResult(viewModel);
            timer.Interval = new TimeSpan(0, 0, 0, 1);
            //timer.Tick += new EventHandler(timer_Tick);
            timer.Tick += timer_Tick;
            timer.Start();
            DateTime startTime = DateTime.Now;
            // Reset message label
            if (message.Text.Length > 0)
            {
                message.Text = "";
            }
            // Reset result text box
            if (resultTextBox.Text.Length > 0)
            {
                resultTextBox.Text = "";
            }
        }
        private void timer_Tick(object sender, object e)
        {
            Countdown.Text = tick + " second(s) ";
            if (tick > 0)
                tick--;
            else
            {
                Countdown.Text = "Times Up";
                timer.Stop();
                submitButton.IsEnabled = false;
                resultTextBox.IsEnabled = false;
                startButton.IsEnabled = true;
                tick = 60;
            }
        }
        private void submitButton_Click(object sender, RoutedEventArgs e)
        {
            timer.Stop();
            submitButton.IsEnabled = false;
            resultTextBox.IsEnabled = false;
            if (System.Text.RegularExpressions.Regex.IsMatch(resultTextBox.Text, "[^0-9]"))
            {
                MessageDialog msgDialog = new MessageDialog("Please enter only numbers.");
                msgDialog.ShowAsync();
                resultTextBox.Text.Remove(resultTextBox.Text.Length - 1);
                //Reset buttons to answer again
                submitButton.IsEnabled = true;
                resultTextBox.IsEnabled = true;
                timer.Start();
            }
            else
            {
                try
                {
                    int userinput = Int32.Parse(resultTextBox.Text);
                    if (userinput == result)
                    {
                        message.Text = "Bingo!";
                        App.player.UpdateScore();
                        startButton.IsEnabled = true;
                    }
                    else
                    {
                        message.Text = "Wrong, sorry...";  
                        startButton.IsEnabled = true;
                    }
                }
                catch (Exception ex)
                {
                    MessageDialog msgDialog = new MessageDialog(ex.Message);
                    msgDialog.ShowAsync();
                    submitButton.IsEnabled = true;
                    resultTextBox.IsEnabled = true;
                    timer.Start();
                }

            }
        }

C# 在 Windows 应用商店应用中重置倒数计时器 - 调度程序计时器

在我看来

,你在这里至少有两个重大问题。一个是你的计时器可能会给用户超过 60 秒,因为 Windows 线程调度程序中的不准确性(即每个时钟周期将以略多于 1 秒的间隔发生(。另一个(与您的问题更相关(是,除非计时器已过,否则不会将tick值重置为 60。

对于后一个问题,最好在启动计时器时简单地重置倒计时值,而不是试图记住停止它的所有位置。

要解决这个问题和第一个问题,请完全删除tick字段,并将代码更改为如下所示:

    static readonly TimeSpan duration = TimeSpan.FromSeconds(60);
    System.Diagnostics.Stopwatch sw;
    private void startButton_Click(object sender, RoutedEventArgs e)
    {
        // Once clicked then disabled
        startButton.IsEnabled = false;
        // Enable buttons required for answering 
        resultTextBox.IsEnabled = true;
        submitButton.IsEnabled = true;
        var viewModel = App.equation.GenerateEquation();
        this.DataContext = viewModel;
        result = App.equation.GetResult(viewModel);
        sw = System.Diagnostics.Stopwatch.StartNew();
        timer.Interval = new TimeSpan(0, 0, 0, 1);
        timer.Tick += timer_Tick;
        timer.Start();
        // Reset message label
        if (message.Text.Length > 0)
        {
            message.Text = "";
        }
        // Reset result text box
        if (resultTextBox.Text.Length > 0)
        {
            resultTextBox.Text = "";
        }
    }
    private void timer_Tick(object sender, object e)
    {
        if (sw.Elapsed < duration)
        {
            Countdown.Text = (int)(duration - sw.Elapsed).TotalSeconds + " second(s) ";
        }
        else
        {
            Countdown.Text = "Times Up";
            timer.Stop();
            submitButton.IsEnabled = false;
            resultTextBox.IsEnabled = false;
            startButton.IsEnabled = true;
        }
    }

这样,tick 事件何时发生并不重要,代码仍将正确计算实际剩余时间并将其用于显示并判断时间是否结束。