Click here to Skip to main content
15,889,281 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
I'll make my description as detailed as possible. thanks in advance.

Is there a way to declare many timers like using array or other methods? and stop the timer when timer expires or time has elapsed?

I have tried t.Stop(); and other timer methods but i cant make it work. this code shows the message box every minute or whatever the user inputted in the timer. The problem is that i can seem to stop a timer when i have multiple timers.

I have a form that allows the user to input the timer,for example 1 minute, this form pops up when i selected a row in the data grid view, the code converts the Hours or minutes into seconds and is working fine.

C#
private void button1_Click(object sender, EventArgs e)
    {
        if (textBox1.Text == "")
        {
            MessageBox.Show("Please Indicate How Many Minutes/Hours.");
        }
        else
        {
            string desu = textBox1.Text;
            int temp = 0;
            if (int.TryParse(desu, out temp))
            {
                if (comboBox1.Text == "Hours")
                {
                    //hours to seconds
                    time = temp * 3600;
                    eta = desu + "Hours";

                    this.Close();
                }
                else if (comboBox1.Text == "Minutes")
                {
                    //minutes to seconds
                    time = temp * 60;
                    eta = desu + "Minutes";

                    this.Close();
                }
            }
            else
            {
                MessageBox.Show("Please enter a valid integer");
            }
        }
    }


after you input the timer, after 1 minute a message box will appear and stop the current timer.

here is the method to call when starting the timer

C#
public void Start()
    {


        ETA_Input frm = new ETA_Input(this);
        startTime = DateTime.Now;
        t = new System.Timers.Timer(1000 * f);
        t.Elapsed += timer_Elapsed;
        t.Enabled = true;

    }


and then here is where it trigger the form where you can input hours or minutes, and pass the row value to the list view while changing one of the value in the datagridview and to the databse.

C#
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
        ETA_Input frm = new ETA_Input(this);
        frm.ShowDialog();
        if (frm.time != 0)
        {
            string name = dataGridView1.CurrentRow.Cells[0].Value.ToString();
            int deku = Int32.Parse(name);
            string constring = "server=localhost;database=dbhorizon;uid=root;password=1234";
            string Query = "update tblUserIdd set User_Available = 'Ongoing' where User_ID='" + deku + "' ";

            MySqlConnection conDatabase = new MySqlConnection(constring);
            MySqlCommand cmdDatabase = new MySqlCommand(Query, conDatabase);
            MySqlDataReader myReader;

            conDatabase.Open();
            myReader = cmdDatabase.ExecuteReader();
            dgvref();

            string id = dataGridView1.CurrentRow.Cells[0].Value.ToString();
            string naem = dataGridView1.CurrentRow.Cells[1].Value.ToString();
            string field = dataGridView1.CurrentRow.Cells[2].Value.ToString();

            f = frm.time;

            Start();



            seconds = string.Format("{0:HH:mm:ss tt}", DateTime.Now);


            string[] row = { id, naem, field, seconds, frm.eta,custb  };
            var listViewItem = new ListViewItem(row);
            listView1.Items.Add(listViewItem);


        }

    }


and here is the time elapsed event where i intended to stop the timer that the time has expired and remove the item in the list view while changing a value in the datagridview to the database. i cant also seem to remove the item where the time has expired or elapsed.


C#
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        TimeSpan timeSinceStart = DateTime.Now - startTime;
        MessageBox.Show("A Service is finished");

        string name = dataGridView1.CurrentRow.Cells[0].Value.ToString();
        int deku = Int32.Parse(name);
        string constring = "server=localhost;database=dbhorizon;uid=root;password=1234";
        string Query = "update tblUserIdd set User_Available = 'Available' where User_ID='" + deku + "' ";

        MySqlConnection conDatabase = new MySqlConnection(constring);
        MySqlCommand cmdDatabase = new MySqlCommand(Query, conDatabase);
        MySqlDataReader myReader;

        conDatabase.Open();
        myReader = cmdDatabase.ExecuteReader();
        dgvref();
    }


What I have tried:

Ive tried a bunch of stuffs which i found out is not really related to what i want to do.
Posted
Updated 25-Aug-17 5:07am
Comments

Instead of creating new timers each time - which is a bad idea, they are a scarce resource in Windows - set up a DateTime collection of end times and use a single running timer to check each of them against DateTime.Now
When you find an elapsed period, remove it from the collection and do your processing. The timer continues running and keeps checking the collection each Tick event until it find work to do.
 
Share this answer
 
Running a lot of Timers can drain resources. It would be wiser to have a single timer and a list of Tasks. Then on an interval, checks if a Task is to be started, executes the task. Your Task/Job could look like this:
C#
class Job
{
    public bool Activated { get; set; }
    public Task<Action> UnitOfWork { get; set; }
    public DateTime StartAt { get; set; }
}

Then to prime:
C#
public static List<Job> Jobs { get; set; } = new List<Job>();

private static void AddJob()
{
    Jobs.Add(new Job
    {
        StartAt = DateTime.Now + new TimeSpan(0, 0, 10),
        UnitOfWork = (Task<Action>)DoATask()
    });
}

private static async Task DoATask()
{
    // do async work here...
}

And to use, setting the timer to 1 second intervals for periodical checking:
C#
private static void T_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    var newJobs = Jobs.Where(x => x.StartAt <= DateTime.Now && !x.Activated);
    foreach (var job in newJobs)
    {
        job.Activated = true;
        job.UnitOfWork.Start();
    }
}

This is a fire and forget model. If multiple jobs are set the same start time, they will all run. The actual job that runs does all the tracking and cleanup.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900