У меня есть приложение C # Windows Forms, и я хочу, чтобы пользователь мог планировать повторяющуюся задачу

1

Мое приложение отправляет электронное письмо на основе данных из введенной формы в пользовательском интерфейсе. Пользовательский интерфейс также позволяет им "планировать" это как работу. Я действительно не хочу использовать внешние классы, например Quartz. Я также не хочу использовать планировщик задач, поскольку для этого потребуется полностью переписать мое приложение... Я понимаю, что это можно сделать с помощью таймеров, и я попытался использовать Windows.Forms.Timer, однако я не получение желаемых результатов. Я хочу, чтобы он выполнялся с заданным пользователем интервалом и временем до установленной даты окончания.

private void Submit_Btn_Click(object sender, EventArgs e)
    {
        bool run = false;
        Location_Alert_Timer.Tick += new EventHandler(Location_Alert_Timer_Tick);

        if (Schedule_Chk.Checked == true)
        {
            run = true;

            if (Recur_Txt.Text != "" || Recur_Txt.Text != "0")
            {
                while (run == true)
                {

                    if ((Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy HH:mm")) <= Convert.ToDateTime(End_Date.Value.ToString("MM/dd/yyyy") + " " + Recur_Time_Txt.Text)))
                    {
                        //Execute_Command();
                        DateTime dt1;
                        DateTime dt2;
                        TimeSpan ts = new TimeSpan(Convert.ToInt16(Recur_Txt.Text),0,0,0);
                        //TimeSpan ts = new TimeSpan(0,0,30);
                        dt1 = Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy HH:mm"));
                        dt2 = Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy") + " " + Recur_Time_Txt.Text);
                        if  (dt1 >= dt2)
                        {
                            Execute_Command();
                            Location_Alert_Timer.Interval = (Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy") + " " + Recur_Time_Txt.Text + ":00.000").Add(ts) - DateTime.Now).Milliseconds;
                            Location_Alert_Timer.Start();
                            while (Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy HH:mm")) <= Convert.ToDateTime(End_Date.Value.ToString("MM/dd/yyyy") + " " + Recur_Time_Txt.Text))
                            {
                                Application.DoEvents();
                            }
                        }
                        else
                        {
                            Location_Alert_Timer.Interval = (Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy") + " " + Recur_Time_Txt.Text + ":00.000") - DateTime.Now).Milliseconds;
                            Location_Alert_Timer.Start();
                            while (exitFlag == false)
                            {
                                Application.DoEvents();
                            }
                        }
                    }
                    else
                    {
                        Location_Alert_Timer.Stop();
                        run = false;
                    }
                }
            }
            else
            {
                Execute_Command();
            }
        }
        else
        {
            Execute_Command();
        }
    }

    void Location_Alert_Timer_Tick(object sender, EventArgs e)
    {
        if (Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy HH:mm")) <= Convert.ToDateTime(End_Date.Value.ToString("MM/dd/yyyy") + " " + Recur_Time_Txt.Text))
        {
            Execute_Command();
        }
        else
        {
            exitFlag = true;
        }
    }

Мои события таймера, похоже, не срабатывают правильно, и я знаю, что это потому, что я неправильно настроил их...

Вот форма UI: Изображение 174551

Если у кого-то есть аналогичная реализация в будущем, объяснение @itsmatt побудило меня переписать все мое событие, с самого начала... ниже - окончательная реализация, и это работает фантастически:

        private void Submit_Btn_Click(object sender, EventArgs e)
    {
        bool run = false;


        if (Schedule_Chk.Checked == true)
        {
            run = true;

            if (Recur_Txt.Text != "" || Recur_Txt.Text != "0")
            {
                while (run == true)
                {
                    if ((Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy HH:mm")) <= Convert.ToDateTime(End_Date.Value.ToString("MM/dd/yyyy") + " " + Recur_Time_Txt.Text)))
                    {
                        DateTime dt1;
                        DateTime dt2;
                        TimeSpan ts = new TimeSpan(Convert.ToInt16(Recur_Txt.Text),0,0,0);
                        dt1 = Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy HH:mm"));
                        dt2 = Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy") + " " + Recur_Time_Txt.Text);
                        if (dt1 >= dt2)
                        {
                            Execute_Command();
                            Location_Alert_Timer.Interval = Convert.ToInt32((Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy") + " " + Recur_Time_Txt.Text + ":00.000").Add(ts) - DateTime.Now).TotalMilliseconds);
                            Location_Alert_Timer.Start();
                            timerActive = true;
                            TimerHold();
                        }
                        else
                        {
                            Location_Alert_Timer.Interval = Convert.ToInt32((Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy") + " " + Recur_Time_Txt.Text + ":00.000") - DateTime.Now).TotalMilliseconds);
                            singleuse = true;
                            Location_Alert_Timer.Start();
                            timerActive = true;
                            TimerHold();
                            MessageBox.Show(DateTime.Now.ToString());
                            MessageBox.Show(DateTime.Now.Add(ts).ToString());
                            MessageBox.Show((Convert.ToDateTime(DateTime.Now.Add(ts).ToString()) - DateTime.Now).TotalMilliseconds.ToString());
                            Location_Alert_Timer.Interval = Convert.ToInt32((Convert.ToDateTime(DateTime.Now.Add(ts).ToString()) - DateTime.Now).TotalMilliseconds);
                            Location_Alert_Timer.Start();
                            timerActive = true;
                            TimerHold();
                        }
                    }
                    else
                    {
                        Location_Alert_Timer.Stop();
                        run = false;
                    }
                }
            }
        }
    }

    public void TimerHold()
    {
        while (timerActive)
        {
            Application.DoEvents();
        }
    }

    void Location_Alert_Timer_Tick(object sender, EventArgs e)
    {
        if (singleuse)
        {
            if (uses < 1)
            {
                if (Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy HH:mm")) <= Convert.ToDateTime(End_Date.Value.ToString("MM/dd/yyyy") + " " + Recur_Time_Txt.Text))
                {
                    uses++;
                    //DoItOnce();
                    Execute_Command();
                }
                else
                {
                    timerActive = false;
                }
            }
            else
            {
                singleuse = false;
                timerActive = false;
                Location_Alert_Timer.Stop();
            }
        }
        else
        {
            if (Convert.ToDateTime(DateTime.Now.ToString("MM/dd/yyyy HH:mm")) <= Convert.ToDateTime(End_Date.Value.ToString("MM/dd/yyyy") + " " + Recur_Time_Txt.Text))
            {
                //DoIt();
                Execute_Command();
            }
            else
            {
                timerActive = false;
            }
        }
    }
  • 0
    Вы притворяетесь, что ваше приложение работает вечно? from msdn "Этот таймер оптимизирован для использования в приложениях Windows Forms и должен использоваться в окне."
  • 1
    используйте quartz-scheduler.net для таких работ
Показать ещё 9 комментариев
Теги:
timer
winforms
.net-3.5

2 ответа

0
Лучший ответ

@kclewis Регистрация обработчика события тика в обработчике нажатия кнопки отправки, как и в случае с вызовом Location_Alert_Timer_Tick(), который вызывается при первом нажатии кнопки, дважды в следующий раз и т.д. Он снова и снова регистрирует одну и ту же функцию обратного вызова, что приводит к нескольким вызовам, возникающим при активации события tick. Вместо этого + = этот обработчик событий во время init (может быть в конструкторе или какой-либо другой функции setup()). Таким образом вы получаете один и только один вызов функции в Location_Alert_Timer_Tick(), когда событие таймера помечается. Добавлено через wiki сообщества для @itsmatt

2

как насчет использования чего-то вроде этого примера?

A-Простой планировщик-в-Csharp

  • 0
    Этот пример, я думаю, сработает, но я надеялся сделать это с как можно меньшим переопределением. Ваш aswer отличный, и я могу использовать его для будущей реализации, но это может быть немного сложным для меня прямо сейчас ... Я новичок в этом и ищу простые решения, но которые позволяют мне выполнять работу.
  • 0
    Ну, я не думаю, что есть действительно простое надежное решение, я боюсь ... Вы могли бы использовать часть кода из примера Project. Я всегда чувствую, что не имею никакого контроля, когда планирую задачи в приложении формы.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню