C#在Windows Store应用中重置倒数计时器-DispatcherTimer- [英] C# Reset a countdown timer-DispatcherTimer- in windows store app

查看:257
本文介绍了C#在Windows Store应用中重置倒数计时器-DispatcherTimer-的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是C#新手,并且是一般编程人员,我正在尝试使用倒数计时器构建数学测验应用.

I'm a C# newbie_and in programming in general_ and Ι'm trying to build a math quiz app with a countdown timer.

每次用户单击开始"按钮时,我都会生成一个方程式,并且给他最多60秒的回答时间.用户回答-他的回答是对还是错都没关系-并且他/她可以再次单击以获取新的等式.因此,我希望计时器在每次向用户显示新的随机方程式时重置.到目前为止,我只设法在60秒的时间间隔过去后将其重置,但即使它不能正常工作,有时也显示59或58秒而不是60秒.

I generate an equation each time the user clicks the start button and I give him a max 60 seconds to answer. The user answers -whether his answer is wrong or right doesn't matter_ and can he/she can click again for a new equation. So I want the timer to reset each time the user is shown a new random equation. So far I've only managed to reset this when the 60sec timespan elapses but even that is not working properly, sometimes it displays 59 or 58 secs instead of 60.

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

So far reading other questions has't helped me much and the timer confuses me. I also accept suggestions to make my code simpler and more elegant.

这是我的代码:

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


            }
        }

推荐答案

在我看来,您在这里至少有两个重要的问题.一种是由于Windows线程调度程序中的不准确,您的计时器可能会给用户60秒钟以上的时间(即,每个滴答声将以略大于1秒的间隔出现).另一个(与您的问题更相关)是,除非计时器已过去,否则您不要将tick值重置为60.

It seems to me that you have at least two significant problems here. One is that your timer will likely give the user more than 60 seconds, due to the inaccuracy in the Windows thread scheduler (i.e. each tick will occur at slightly more than 1 second intervals). The other (and more relevant to your question) is that you don't reset the tick value to 60 except when the timer has elapsed.

对于后一个问题,最好是在启动计时器时简单地重置倒计时值,而不是尝试记住在任何地方停止它的时间.

For the latter issue, it would be better to simply reset your countdown value when you start the timer, rather than trying to remember everywhere that you stop it.

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

To fix that and the first issue, get rid of the tick field altogether and change your code to look more like this:

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

这样,计时事件发生时 并不重要,代码仍然可以正确计算实际剩余时间,并将其用于显示并判断时间是否到了.

This way, it won't matter exactly when the tick event happens, the code will still correctly compute the actual time remaining and use that for the display and to tell whether the time is up.

这篇关于C#在Windows Store应用中重置倒数计时器-DispatcherTimer-的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆