Остановка DispatcherTimer нажатием кнопки - PullRequest
0 голосов
/ 01 мая 2019

Когда я нажимаю кнопку «Стоп», мой таймер продолжает обратный отсчет, даже если я приказываю ему остановиться.

Мой текущий соответствующий код:

Я называю здесь таймеры,поскольку мне нужно получить к ним доступ и для кнопки «Стоп / Пуск».

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

Когда я нажимаю кнопку «Вкл», вызывается метод 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 
        }

1 Ответ

1 голос
/ 01 мая 2019

Проблема в вашем коде заключается в том, что вы инициализируете motorTimer_1 с DispatcherTimer, который ничего не делает, затем вы передаете motorTimer_1 в качестве параметра dispatcherTimer, а затем заменяете значение параметра с недавно созданным, другим DispatcherTimer.

Новый таймер работает нормально, но когда вы вызываете stop на motorTimer_1, ничего не происходит, потому что это не тот, который работает. Вы можете просто назначить новый DispatcherTimer непосредственно на motorTimer_1 в IndividualTestStart(), но у вас возникли большие проблемы с параметризацией всего в IndividualTestStart(), чтобы он мог работать с различными DispatcherTimers.

Вместо этого, вот что мы сделаем: нет никаких причин для передачи DispatcherTimer. IndividualTestStart() должен создать 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, вам нужно написать класс Viewmodel TimerThing (придумайте более подходящее имя), которому принадлежит DispatcherTimer, две команды для его запуска и остановки и открытое свойство bool, указывающее, является ли он работает или нет. IndividualTestStart () должен быть методом этого класса. Родительская модель представления будет иметь ObservableCollection<TimerThing>, содержащую произвольное число TimerThing s, которое будет отображаться в ItemsControl с ItemTemplate, который создает кнопки, связанные с командами Start и Stop. Приведенный выше код будет выглядеть совсем иначе, поскольку ни один из кодов C # не будет ничего знать о кнопках: вместо этого кнопки в шаблоне элемента XAML будут включены / отключены привязками.

...