C#重置Windows应用商店应用中的倒数计时器-DispatcherTimer-

时间:2014-12-19 12:39:39

标签: c# windows-store-apps reset countdown dispatchertimer

我是一名C#newbie_和一般的编程,我试图用倒数计时器建立一个数学测验应用程序。

每次用户点击开始按钮时,我都会生成一个等式,我给他最多60秒的时间来回答。用户回答 - 他的回答是错误还是无关紧要_并且他/她可以再次点击以获得新的等式。所以我希望每次为用户显示一个新的随机方程时重置计时器。到目前为止,我只是在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();
                }


            }
        }

1 个答案:

答案 0 :(得分:2)

在我看来,你在这里至少有两个重大问题。一个是由于Windows线程调度程序的不准确性,您的计时器可能会给用户超过60秒(即每个节拍将以稍微超过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;
        }
    }

这样,当发生滴答事件时,它确实无关紧要,代码仍将正确计算剩余的实际时间并将其用于显示并告知时间是否为起来。