【问题标题】:Stopping DispatcherTimer with a button click通过单击按钮停止 DispatcherTimer
【发布时间】:2019-05-01 15:16:06
【问题描述】:

当我点击停止按钮时,我的计时器仍在倒计时,即使我告诉它停止。

我目前的相关代码:

我在这里命名计时器,因为我还需要访问它们以获得停止/启动所有按钮。

namespace Row_Interface
{
    public partial class MainWindow : Window
    {
        //Declare the timers here, so the stop all button can access them as well
        DispatcherTimer motorTimer_1 = new DispatcherTimer();
        TimeSpan motorCycleTime_1 = TimeSpan.FromSeconds(0);

当我点击 on 按钮时,IndividualTestStart 方法被调用并传递了相关参数:

public void motorOnBtn_1_Click(object sender, RoutedEventArgs e)
        {
            IndividualTestStart(motorOnBtn_1, motorOffBtn_1, motorTimer_1, motorCycleTime_1, timeUntilmotorCycle_1, motorTestCycles_1);
        }

当我单击关闭按钮时,我想停止该计时器,以便循环永远不会结束:

        private void motorOffBtn_1_Click(object sender, RoutedEventArgs e)
        {
            motorTimer_1.Stop();
            motorOnBtn_1.IsEnabled = true; //Enables the start test button
            motorOffBtn_1.IsEnabled = false; //Disables the stop test button

        }

当我单击开始时调用它。我最终会有类似的停止按钮,但我一步一步地采取措施:

private void IndividualTestStart(Button startButton, Button stopButton, DispatcherTimer dispatcherTimer, TimeSpan timeSpan, TextBox timeRemaining, TextBox cycleCount)
        {
            stopButton.IsEnabled = true; //Enables the stop button

            //Set the time to run. This will be set from the database eventually.
            timeSpan = TimeSpan.FromSeconds(10);

            //Set up the new timer. Updated every second.
            dispatcherTimer = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate
            {
                timeRemaining.Text = timeSpan.ToString("c"); //Sets the text in the textbox to the time remaining in the timer
                startButton.IsEnabled = false; //Disables the start test button once the test is started
                if (timeSpan == TimeSpan.Zero) //Checks to seee if the time has run out
                {
                    dispatcherTimer.Stop(); //Stops the timer once the time has run out
                    startButton.IsEnabled = true; //Enables the start test button
                    int initialCycleCount = 0;
                    initialCycleCount++;
                    cycleCount.Text = initialCycleCount.ToString();
                    stopButton.IsEnabled = false;//Disables the stop button

                }
                timeSpan = timeSpan.Add(TimeSpan.FromSeconds(-1)); //Subtracts one second each time the timer "ticks"
            }, Application.Current.Dispatcher);  //runs within the UI thread

            dispatcherTimer.Start(); //Starts the timer 
        }
}

当我单击停止按钮时,我希望文本框中的计时器停止倒计时。但是,它只是不断滴答作响。当我单击停止时,开始按钮被重新启用,所以我知道它正在触发事件处理程序中的代码。但它并没有停止计时器。

现在没有开始新的计时器。 新代码:

        public void motorOnBtn_1_Click(object sender, RoutedEventArgs e)
        {
            IndividualTestStart(motorOnBtn_1, motorOffBtn_1, motorTimer_1, motorCycleTime_1, timeUntilmotorCycle_1, motorTestCycles_1);
        }

        private void IndividualTestStart(Button startButton, Button stopButton, DispatcherTimer dispatcherTimer, TimeSpan timeSpan, TextBox timeRemaining, TextBox cycleCount)
        {
            stopButton.IsEnabled = true; //Enables the stop button

            //Set the time to run. This will be set from the database eventually.
            timeSpan = TimeSpan.FromSeconds(10);

            {
                timeRemaining.Text = timeSpan.ToString("c"); //Sets the text in the textbox to the time remaining in the timer
                startButton.IsEnabled = false; //Disables the start test button once the test is started
                if (timeSpan == TimeSpan.Zero) //Checks to seee if the time has run out
                {
                    dispatcherTimer.Stop(); //Stops the timer once the time has run out
                    startButton.IsEnabled = true; //Enables the start test button
                    int initialCycleCount = 0;
                    initialCycleCount++;
                    cycleCount.Text = initialCycleCount.ToString();
                    stopButton.IsEnabled = false;//Disables the stop button

                }
                timeSpan = timeSpan.Add(TimeSpan.FromSeconds(-1)); //Subtracts one second each time the timer "ticks"
            };  //runs within the UI thread

            dispatcherTimer.Start(); //Starts the timer 
        }

【问题讨论】:

  • 您将motorTimer_1 作为参数dispatcherTimer 传递给IndividualTestStart()。然后用新创建的DispatcherTimer 替换参数的值,然后初始化并启动它。 motorTimer_1 永远不会启动,也永远不会引用实际运行的 DispatcherTimer
  • 啊,有道理。但是,我删除了该参数值的替换,现在计时器根本不会滴答作响。现在正在努力。
  • 停下来想一想。您现在如何初始化 DispatcherTimer motorTimer_1?你给它一个间隔、一个优先级、一个委托、一个调度程序吗?在哪里?如何?您是否像以前一样创建一个新的 DispatcherTimer,但只是将其丢弃而不是将其分配给参数?让我们看看新代码。
  • ```` timeSpan = TimeSpan.FromSeconds(10); { timeRemaining.Text = timeSpan.ToString("c"); //将文本框中的文本设置为计时器中的剩余时间 if (timeSpan == TimeSpan.Zero) { dispatcherTimer.Stop(); } timeSpan = timeSpan.Add(TimeSpan.FromSeconds(-1)); }; dispatcherTimer.Interval = new TimeSpan(0, 0, 1); dispatcherTimer.Start(); //启动定时器 } ````
  • 请将其添加到问题中,以便我阅读。

标签: c# wpf button dispatchertimer


【解决方案1】:

您的代码中的问题是您使用不执行任何操作的DispatcherTimer 初始化motorTimer_1,然后将motorTimer_1 作为dispatcherTimer 参数传入,然后替换参数的值使用新创建的不同DispatcherTimer

新计时器工作正常,但是当您在 motorTimer_1 上调用 stop 时,什么也没有发生,因为那不是正在运行的计时器。您可以简单地将新的DispatcherTimer 直接分配给IndividualTestStart() 中的motorTimer_1,但是您在参数化IndividualTestStart() 中的所有内容时遇到了很大的麻烦,因此它可以与不同的DispatcherTimers 一起使用。

相反,我们将这样做:没有理由传递DispatcherTimerIndividualTestStart() 必须创建 DispatcherTimer 才能对其进行初始化。好的,让我们开始吧。它将创建一个新的并返回它。

private DispatcherTimer IndividualTestStart(Button startButton, Button stopButton, 
    TimeSpan timeSpan, TextBox timeRemaining, TextBox cycleCount)
{
    stopButton.IsEnabled = true; //Enables the stop button

    //Set the time to run. This will be set from the database eventually.
    timeSpan = TimeSpan.FromSeconds(10);

    //  Set up the new timer. Updated every second.
    var dispatcherTimer = new DispatcherTimer(new TimeSpan(0, 0, 1), DispatcherPriority.Normal, delegate
    {
        timeRemaining.Text = timeSpan.ToString("c"); //Sets the text in the textbox to the time remaining in the timer
        startButton.IsEnabled = false; //Disables the start test button once the test is started
        if (timeSpan == TimeSpan.Zero) //Checks to seee if the time has run out
        {
            dispatcherTimer.Stop(); //Stops the timer once the time has run out
            startButton.IsEnabled = true; //Enables the start test button
            int initialCycleCount = 0;
            initialCycleCount++;
            cycleCount.Text = initialCycleCount.ToString();
            stopButton.IsEnabled = false;//Disables the stop button

        }
        timeSpan = timeSpan.Add(TimeSpan.FromSeconds(-1)); //Subtracts one second each time the timer "ticks"
    }, Application.Current.Dispatcher);  //runs within the UI thread

    dispatcherTimer.Start(); //Starts the timer 

    return dispatcherTimer;
}

public void motorOnBtn_1_Click(object sender, RoutedEventArgs e)
{
    if (motorTimer_1 == null)
    {
        //  Create/initialize a new timer and assign it to motorTimer_1
        motorTimer_1 = IndividualTestStart(motorOnBtn_1, motorOffBtn_1, 
            motorCycleTime_1, timeUntilmotorCycle_1, motorTestCycles_1);
    }
    else
    {
        //  It's already there, just start it. 
        motorTimer_1.Start();
    }
}

由于这是 WPF,您需要编写一个视图模型类 TimerThing(想一个更好的名称),它拥有一个 DispatcherTimer、两个启动和停止它的命令,以及一个指示它是否为跑步与否。 IndividualTestStart() 应该是该类的方法。父视图模型将有一个ObservableCollection<TimerThing>,其中包含任意数量的TimerThings,它将显示在带有一个ItemTemplate 的ItemsControl 中,该ItemTemplate 创建绑定到Start 和Stop 命令的按钮。上面的代码看起来会很不一样,因为没有任何 C# 代码对按钮有任何了解:相反,项目模板 XAML 中的按钮将通过绑定启用/禁用。

【讨论】:

  • 我将开始努力将其实现到我的代码中,谢谢!与此同时,这提出了一个问题。我的印象是,如果您在一个方法中创建了一个计时器,您将无法在另一个方法中访问该计时器。这就是为什么我在方法之外的代码开头创建计时器的原因。我认为情况并非如此,我可以在任何地方访问计时器,只要我通过它的名称来引用它?
  • @Schreiberito 请在motorOnBtn_1_Click 中查看更正的代码,初始版本中存在严重遗漏,破坏了一切。
  • 感谢所有帮助。听起来我需要更多地了解类和绑定,才能真正理解你所指的内容。我今晚会继续努力,一旦我理解得更好,我会继续参考!
  • 所有集合和数据模板的通用术语是“MVVM”,或“模型/视图/视图模型模式”。学习曲线很陡,但功能非常强大,这里有很多人可以帮助您解决问题。玩得开心。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-25
  • 1970-01-01
  • 2016-08-14
  • 2012-12-06
相关资源
最近更新 更多