【发布时间】:2015-01-04 16:44:19
【问题描述】:
我的应用程序根据 UI 上输入的表单中的数据发送一封电子邮件。 UI 还允许他们将其“安排”为工作。我真的不想使用外部课程,例如石英。我也不想使用任务调度程序,因为这需要完全重写我的应用程序......我知道这可以通过计时器来完成,并且我尝试使用 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;
}
}
}
【问题讨论】:
-
您是否假装您的应用程序永远运行?来自 msdn "此计时器已针对在 Windows 窗体应用程序中的使用进行了优化,并且必须在窗口中使用。"
-
这类作品使用quartz-scheduler.net
-
为什么要在按钮回调中注册tick事件?在别处注册。这在 UI 线程上运行。那是你要的吗?也许不是,对吧?还有其他可用的计时器不在 UI 线程上。
-
应用程序现在表现如何..?它至少有响应吗..?
-
@kclewis 像您一样在提交按钮单击处理程序中注册滴答事件处理程序将导致第一次单击按钮时调用 Location_Alert_Timer_Tick() ,下次单击两次等。它是一遍又一遍地注册相同的回调函数,这会导致在引发滴答事件时多次调用该回调函数。相反,在初始化时 += 那个事件处理程序(可能在构造函数或其他一些 setup() 函数中)。这样,当引发计时器滴答事件时,您将获得一个且只有一个对 Location_Alert_Timer_Tick() 的函数调用。
标签: c# .net winforms timer .net-3.5