Мое приложение отправляет электронное письмо на основе данных из введенной формы в пользовательском интерфейсе. Пользовательский интерфейс также позволяет им "планировать" это как работу. Я действительно не хочу использовать внешние классы, например 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:
Если у кого-то есть аналогичная реализация в будущем, объяснение @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;
}
}
}
@kclewis Регистрация обработчика события тика в обработчике нажатия кнопки отправки, как и в случае с вызовом Location_Alert_Timer_Tick(), который вызывается при первом нажатии кнопки, дважды в следующий раз и т.д. Он снова и снова регистрирует одну и ту же функцию обратного вызова, что приводит к нескольким вызовам, возникающим при активации события tick. Вместо этого + = этот обработчик событий во время init (может быть в конструкторе или какой-либо другой функции setup()). Таким образом вы получаете один и только один вызов функции в Location_Alert_Timer_Tick(), когда событие таймера помечается. Добавлено через wiki сообщества для @itsmatt
как насчет использования чего-то вроде этого примера?