我有一个C#Windows窗体应用程序,我希望用户能够安排一个定期任务

我有一个C#Windows窗体应用程序,我希望用户能够安排一个定期任务,c#,.net,winforms,timer,.net-3.5,C#,.net,Winforms,Timer,.net 3.5,我的应用程序根据用户界面上输入表单的数据发送电子邮件。用户界面还允许他们将此作为作业“安排”。我真的不想在课外使用,例如Quartz。我也不想使用任务调度程序,因为这需要完全重写我的应用程序。。。我知道这可以通过定时器来完成,并且我已经尝试使用Windows.Forms.Timer,但是,我没有得到想要的结果。我希望它以用户指定的间隔和时间运行,直到设置的结束日期 private void Submit_Btn_Click(object sender, EventArgs e) {

我的应用程序根据用户界面上输入表单的数据发送电子邮件。用户界面还允许他们将此作为作业“安排”。我真的不想在课外使用,例如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;
        }
    }
private void Submit\u Btn\u单击(对象发送者,事件参数e)
{
bool-run=false;
Location\u Alert\u Timer.Tick+=新事件处理程序(Location\u Alert\u Timer\u Tick);
如果(计划检查==真)
{
run=true;
if(Recur_Txt.Text!=“0”)
{
while(run==true)
{
if((Convert.ToDateTime(DateTime.Now.ToString(“MM/dd/yyyy HH:MM”))=dt2)
{
执行_命令();
Location_Alert_Timer.Interval=(Convert.ToDateTime(DateTime.Now.ToString(“MM/dd/yyyy”)+“”+Recur_Time_Txt.Text+“:00.000”)。添加(ts)-DateTime.Now)。毫秒;
位置\警报\计时器.Start();

while(Convert.ToDateTime(DateTime.Now.ToString(“MM/dd/yyyy HH:MM”))使用类似于此示例的内容怎么样


@kclewis在“提交”按钮单击处理程序中注册勾号事件处理程序,就像您所做的那样,将导致位置\u警报\u计时器\u勾号()第一次单击按钮时调用一次,下一次调用两次,以此类推。它一遍又一遍地注册同一个回调函数,这导致在引发勾号事件时多次调用该回调函数。相反,在初始化时,+=该事件处理程序(可能在构造函数或其他一些setup()函数中)。这样,当计时器滴答声事件引发时,您将得到一个且只有一个对位置\u Alert\u Timer\u Tick()的函数调用。通过社区wiki发布@itsmat

您是否假装应用程序永远运行?来自msdn“此计时器已优化,可用于Windows窗体应用程序,并且必须在窗口中使用。”用于此类工作为什么要在按钮回调中注册勾号事件?在其他位置注册它。这在UI线程上运行。这是您想要的吗?可能不是,对吗?UI线程上没有其他可用计时器。应用程序现在的行为如何?它至少有响应吗?@kclewis注册提交按钮中的勾选事件处理程序单击处理程序会导致位置\u警报\u计时器\u勾选()第一次单击按钮时调用一次,下一次调用两次,以此类推。它一遍又一遍地注册同一个回调函数,这导致在引发勾号事件时多次调用该回调函数。相反,在初始化时,+=该事件处理程序(可能在构造函数或其他一些setup()函数中)。这样,您将得到一个且只有一个对位置的函数调用。\u Alert\u Timer\u Tick()当计时器滴答声事件被触发时。我认为这个例子会起作用,但我希望通过尽可能少的重新定义来完成。你的aswer是一个很好的例子,我可能会在未来的实现中使用它,但现在对我来说可能有点复杂……我对这个问题不熟悉,正在寻找简单的解决方案,但这允许我这么做他在工作。嗯,恐怕没有一个真正简单可靠的解决方案……您可能可以使用示例项目中的一些代码。我总是觉得我无法控制在表单应用程序中调度任务时会发生什么。
        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;
            }
        }
    }