C# 单击按钮停止Dispatchermer

C# 单击按钮停止Dispatchermer,c#,wpf,button,dispatchertimer,C#,Wpf,Button,Dispatchertimer,当我点击我的停止按钮时,我的计时器仍然在倒计时,即使我告诉它停止 我目前的相关代码: 我在这里命名计时器,因为我还需要访问它们的停止/启动按钮 namespace Row_Interface { public partial class MainWindow : Window { //Declare the timers here, so the stop all button can access them as well DispatcherT

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

我目前的相关代码:

我在这里命名计时器,因为我还需要访问它们的停止/启动按钮

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 
        }
}
当我单击停止按钮时,我希望文本框中的计时器停止倒计时。然而,它一直在滴答作响。当我单击stop时,start按钮被重新启用,因此我知道它正在触发事件处理程序中的代码。但它并没有停止计时器

现在不启动新计时器。 新代码:

        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 
        }

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

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

相反,我们要做的是:没有理由传递一个调度员。IndividualTestStart必须创建Dispatcher才能初始化它。好的,让我们开始吧。它将创建一个新的并返回它


因为这是WPF,所以您需要编写一个viewmodel类Timer,考虑一个更好的名称,它拥有一个Dispatcher、两个启动和停止它的命令,以及一个指示它是否正在运行的公共bool属性。IndividualTestStart应该是该类的一个方法。父viewmodel将具有一个ObservableCollection,其中包含任意数量的TimerThings,该TimerThings将显示在ItemsControl中,ItemTemplate创建绑定到Start和Stop命令的按钮。上面的代码看起来非常不同,因为C代码中没有一个对按钮有任何了解:相反,项模板XAML中的按钮将由绑定启用/禁用

将motorTimer_1作为参数Dispatcher传递给IndividualTestStart。然后用新创建的Dispatchermer替换参数值,初始化并启动Dispatchermer。motorTimer_1从未启动,也从未引用实际运行的调度程序。啊,这是有道理的。但是,我删除了该参数值的替换项&现在计时器根本不会滴答作响。现在就开始,停下来好好想想。您现在如何初始化Dispatchermer motorTimer_1?你给它一个间隔,一个优先级,一个委托,一个调度?哪里怎样您是否像以前一样创建了一个新的Dispatcher,但只是将其丢弃,而不是将其分配给参数?让我们看看新代码。```timeSpan=timeSpan.FromSeconds10;{timeRemaining.Text=timeSpan.ToStringc;//如果timeSpan==timeSpan.Zero{dispatcherTimer.Stop;}timeSpan=timeSpan.AddTimeSpan.FromSeconds-1;},则将文本框中的文本设置为计时器中的剩余时间;Dispatchermer.Interval=新时间间隔0,0,1;调度程序启动//启动计时器}```请将其添加到问题中,以便我可以阅读。我将开始在代码中实现此功能,谢谢!同时,这也提出了一个问题。我的印象是,如果你在一个方法中创建了一个计时器,你就不能在另一个方法中访问该计时器。这就是为什么我在代码开始时在方法之外创建计时器的原因。我想不是这样的&我可以在任何地方访问计时器,只要我用它的名字来引用它?@Schreiberito请查看motorOnBtn_1_Click中的更正代码,初始版本中有一个严重的遗漏,这破坏了一切。感谢所有的帮助。听起来我需要学习更多关于类和绑定的知识,才能真正了解您所指的内容。今天晚上我会做这件事的&一旦我理解得更清楚,就把这件事留作参考吧!所有集合和数据模板内容的通用术语是MVVM,或Model/View/Viewmodel模式。学习曲线很陡峭,但它非常强大,这里有很多人可以帮助你克服困难。玩得高兴
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();
    }
}