简体   繁体   中英

Task only run once on Timer

Good day, I'm beginner and trying to learn how to run my long and repeatedly running task on timer.

What I wanted to achieve is to make my method below run every 100 milliseconds. (please correct me if there's something wrong)

  private void Long_Running_Task()
    {
        DateTime timeticking = DateTime.Now;
        using (MySqlConnection ccon = new MySqlConnection(connString))
        {
            ccon.Open();
            MySqlCommand ccom = new MySqlCommand("Select * From table1", ccon);
            MySqlDataReader creader = ccom.ExecuteReader();
            while (creader.HasRows && creader.Read())
            {
                string etime = creader.GetString(creader.GetOrdinal("Time"));
                string etimeformat = creader.GetString(creader.GetOrdinal("TimeFormat"));
                string edate = creader.GetString(creader.GetOrdinal("Date"));
                DateTime tdate = Convert.ToDateTime(edate);
                var newedate = todatetime.ToString("yyyy/MM/dd");
                string expected_datetime_for_report = newedate + " " + etime + " " + etimeformat;
                var selecttimeticking = timeticking.ToString("yyyy/MM/dd hh:mm tt");
                if (selecttimeticking == expected_datetime_for_report)
                {
                    using (MySqlConnection ccon2 = new MySqlConnection(connString))
                    {
                        MySqlCommand ccom2 = new MySqlCommand();
                        string completes = "Complete";
                        ccon2.Open();
                        ccom2 = new MySqlCommand("UPDATE table1 SET Report_Progress=@reportstatus WHERE Date=@day && Time=@time && TimeFormat=@timeformat", ccon2);
                        ccom2.Parameters.AddWithValue("@day", newexpecteddate);
                        ccom2.Parameters.AddWithValue("@time", expectedtime);
                        ccom2.Parameters.AddWithValue("@timeformat", expectedtimeformat);
                        ccom2.Parameters.AddWithValue("@reportstatus", completes);
                        ccom2.ExecuteReader();
                        ccon2.Close();
                    }
                }
            }
            creader.Dispose();
            ccon.Close();
        }
    }

when it comes to functionality of the method, it is doing what is supposed to be doing but only run once when I try this on timer.

    private void Time_Tick(object sender, EventArgs e)
    {
      Task longrun = new Task(()=>Long_Running_Task());
      longrun.Start();
    }

When I put the code of my method to my timer "Time_Tick" it runs again and again with only single problem it lags when I had a lot of data to run on my selected date for example 10/07/2017 11:30 PM.

I know this is kind of big problem somehow but I'm willing to learn, be corrected and take some advice. Thank you so much.

Personally, when I run into an issue like this, I usually tackle it by having the function not get kicked off if there's a previous instance running. Here's a nice class to help take care of it for you:

public class RecurringTask
{
    private Action procedureToRunRepeatedly;
    private Timer timer;
    private Task task;

    public RecurringTask(Action procedureToRunRepeatedly, int millisecondsBetweenRuns)
    {
        this.procedureToRunRepeatedly = procedureToRunRepeatedly;
        this.timer = new Timer();
        this.timer.Tick += TickEvent;
        this.timer.Interval = millisecondsBetweenRuns;
        this.timer.Enabled = true;
    }

    private void TickEvent(object sender, EventArgs e)
    {
        if (task != null)
            if (task.Status == TaskStatus.Running) return;
        task = new Task(procedureToRunRepeatedly);
        task.Start();
    }
}

Basically, all you have to do is create an instance of RecurringTask, feed in the Action that you want it to perform, and how many milliseconds you want between calls. If the task is still running when the next 'tick' occurs, it simply exits out and waits for the next tick.

In my example case, I just did something silly like:

private RecurringTask myTask = new RecurringTask(DoTest, 2000);
public void DoTest()
{
    MessageBox.Show("Hello World");
}

Hope that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM