3

I'm developing a simple app that checks the DB every 60 secs. I use System.Threading.TimerCallback to do that, but, when I run the app, it only ticks once.

Here is the code:

private void Form1_Load(object sender, EventArgs e)
    {
        // Create the delegate for the Timer type. 
        System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(d);

        // Establish timer settings. 
        System.Threading.Timer t = new System.Threading.Timer(
          timeCB,     // The TimerCallback delegate object. 
          null,       // Any info to pass into the called method (null for no info). 
          0,          // Amount of time to wait before starting (in milliseconds). 
          1000);      // Interval of time between calls (in milliseconds). 
    }

    void m(object o)
    {
        System.Media.SystemSounds.Hand.Play();
        SReminderEntities ctx = new SReminderEntities();

        var jobs = (from m in ctx.Messages
                    select m).ToList();

        var seljobs = from j in jobs
                      where j.RemindeTime.Date == DateTime.Now.Date
                            && j.RemindeTime.Hour == DateTime.Now.Hour
                            && j.RemindeTime.Minute == DateTime.Now.Minute
                      select j;

        foreach (var j in seljobs)
        {
           // SendGmail("iReminder", j.Text, new string[] { j.User.Email }, "iReminderSender@Gmail.com");
            //this.sendSMS(j.User.Mobile, j.Text);
            System.Media.SystemSounds.Hand.Play();
        }//foreach
    }

    void d(object o)
    {
        MessageBox.Show("Test");
    }

When I call d it works, but m just runs once. What is the problem and how can I solve it? Thank you.

Adaline Simonian
  • 4,596
  • 2
  • 24
  • 35
Mahmood Jenami
  • 421
  • 1
  • 7
  • 20
  • Delete all code except for the timer. Add a MessageBox into the tick handler. Does it still fire just once? – usr Jan 25 '15 at 15:10

2 Answers2

6

The System.Threading.Timer class requires that you maintain your own reference to it. It doesn't have any rooted data structures itself that would keep the instance reachable. So if you don't keep the reference yourself, the garbage collector will reclaim the object, discarding your timer.

Try creating a private instance field in your form class and store the reference there instead.

See also the documentation, which reads in part:

As long as you are using a Timer, you must keep a reference to it. As with any managed object, a Timer is subject to garbage collection when there are no references to it. The fact that a Timer is still active does not prevent it from being collected.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
0

It's disposing of itself once Form_Load is done. You need to create a Form level reference to the Timer object and then re-construct it on Form_Load with the parameters required.

System.Threading.Timer t = System.Threading.Timer    

private void Form1_Load(object sender, EventArgs e)
        {
            // Create the delegate for the Timer type. 
            System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(d);

            // Establish timer settings. 
              t = new System.Threading.Timer(
              timeCB,     // The TimerCallback delegate object. 
              null,       // Any info to pass into the called method (null for no info). 
              0,          // Amount of time to wait before starting (in milliseconds). 
              1000);      // Interval of time between calls (in milliseconds). 
        }

        void m(object o)
        {
            System.Media.SystemSounds.Hand.Play();
            SReminderEntities ctx = new SReminderEntities();

            var jobs = (from m in ctx.Messages
                        select m).ToList();

            var seljobs = from j in jobs
                          where j.RemindeTime.Date == DateTime.Now.Date
                                && j.RemindeTime.Hour == DateTime.Now.Hour
                                && j.RemindeTime.Minute == DateTime.Now.Minute
                          select j;

            foreach (var j in seljobs)
            {
               // SendGmail("iReminder", j.Text, new string[] { j.User.Email }, "iReminderSender@Gmail.com");
                //this.sendSMS(j.User.Mobile, j.Text);
                System.Media.SystemSounds.Hand.Play();
            }//foreach
        }
Chase
  • 162
  • 1
  • 10