简体   繁体   中英

Schedule Job using System.Threading?

I am trying to implement Scheduled Job using System.Threading .

My code is running for the first time correctly and store the log in the database but than timer is not calling back after the time interval.

I am following the example on the link [example] http://dhavalupadhyaya.wordpress.com/2008/08/30/how-to-create-scheduled-jobs-in-net-web-applications/

My implementation is as:

 public sealed class Jobs
    {
        public Jobs() { }

        public static void HourlyJob(object state)
        {
            SchedularDBContext schedular = new SchedularDBContext();
            DBSchedulars dbSchedular = new DBSchedulars();

            dbSchedular.Message = "Generated time span = " + DateTime.Now.ToString();
            schedular.DbSchedulars.Add(dbSchedular);
            schedular.SaveChanges();


        }

    }

    public sealed class Schedular
    {
        public Schedular() { }
        public void Schedular_Start()
        {
            TimerCallback callbackHourly = new TimerCallback(Jobs.HourlyJob);
            Timer hourlytimer = new Timer(callbackHourly, null, TimeSpan.Zero,TimeSpan.FromMinutes(1.0));
        }
    }

I am calling it in global.ascx as

 protected void Application_Start(object sender, EventArgs e)
        {
            CodeFiles.Schedular objSchedular = new CodeFiles.Schedular();
            objSchedular.Schedular_Start();
        }

But the timer is running for the first time after that it is not running. I want it to run after every minute. What's wrong in it? And how could I make it to run after every minute automatically?

You've faced with the problem of disposed timer - your objSchedular is not referenced anywhere after executing Application_Start and also internally your Schedular instance doesn't hold reference to .NET Timer object. So garbage collector sees your objects as garbage, because no references is found to those objects, so timer is disposed during GC cycle.
I would recommend to read Richter's CLR via C# "Garbage Collections and Debugging" where he shows this pitfall with Timer object. So store reference to your objSchedular as a field and inside it store hourlytimer variable as a field and this will fix your problem.

A fast answer is that you need to make your object static, and declare it somewhere else and not inside the Application Start. On application start you only need to call the objSchedular.Schedular_Start();

 CodeFiles.Schedular static objSchedular = new CodeFiles.Schedular();

Its all about maintaining scope of the Timer object

2 Options

  1. Pass Timer object to the constructor of " Shceduler " class and use it

  2. If you need to create many Timer objects in " Shceduler " class, create a List<Timer> and pass it to constructor of Scheduler Class. Add newly created Timer object to this list . But make sure to release the timers from list once you dont need them.

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