|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionThis article will help you build a recurring task scheduler that will execute at specified interval of time. This article overcomes the complexity of scheduling applications that you may find on this site or on internet. This small and easy to understand code overcomes the limitation of installing a web service (with special permission) or windows service or instantiate any other process to run scheduler. It is safe to run on shared hosting provider if coded carefully and with the ability to shut down the task if needed. BackgroundFirst of all let me give a full credit to Michael Taper at angrycoder.com who first wrote the code (idea behind how this works) in C# back in April 2003. I'm giving credit to this guy since it appears that he wrote that article. Since I’ve run into his code in 2008 with ASP.NET 3.5 around and I need to work on the VB.NET version I could not make this code run for me in VB.NET. Also the originals coder description on that site was poor in explaining what his code actually does (it is very high overview)– so I decided to convert his C# code to VB.NET version that will run on today’s .NET version (2.0 or greater as of March 2008) and to bring down to the level for not so advanced coders. Using the codeI've placed the whole code in single file that is constructed like this:
The ISchedulerJob Interface is only one line of code that will execute each class that it implements it. Public Interface ISchedulerJob
Sub Execute()
End Interface
That is plan simple. The sub Execute line tells each class that implements it, that this call must be defined and implement for this interface. This ensured the Execute event will fire on each scheduled job. Now lets get to second step implementing this intefaces in our classes. My need for this scheduler was to check the website database and send e-mail to users that satisfy certain criteria. The logic behind this is not included since it goes beyond the scope of this article. The fist class MailJob is actually reperesents a single job that will be executed on the schedule: Public Class MailJob
Implements ISchedulerJob
Public Sub Execute() Implements ISchedulerJob.Execute
MMCUtil.SendMail("tosomeone@domain.com", _
"Subject:testing schedule from mail job ",
"Body:Body of schedule")
End Sub
End Class
You can see that this classs implements Execute sub of our Job Interface and all it does is calling my SendMail function. The next class is just for demonstration puposes. It represents another job that will be executed at the same time as the MailJob Class. Public Class OtherJob
Implements ISchedulerJob
Public Sub Execute() Implements ISchedulerJob.Execute
MMCUtil.SendMail("tosomeone@domain.com", _
"Subject:testing schedule from other job ", _
"Body:Body of other job schedule")
End Sub
End Class
As you can see it does exactly same as previous job but the subject and body are different so it technically is different job to execute. You can add as many job classes as you like. The job classes does not have to be executed. To include the job in the the execution schedule each job class has to instantiated. I will discuss in more detail later on how to achive this. The next step is to build configuration class. The configuration has two properties. One Integer that keeps the time (in milliseconds) that you wish to wait before the scheduled jobs execute, and one ArrayList that keeps Jobs to be executed.
Public Class SchedulerConfiguration
Private m_sleepInterval As Integer
Private m_jobs As New ArrayList()
Public ReadOnly Property SleepInterval() As Integer
Get
Return m_sleepInterval
End Get
End Property
Public ReadOnly Property Jobs() As ArrayList
Get
Return m_jobs
End Get
End Property
Public Sub New(ByVal newSleepInterval As Integer)
m_sleepInterval = newSleepInterval
End Sub
End Class
The scheduler engine is the one that makes the jobs run. This is where you will wan to pay some attention (design your code carefully), since the jobs are recurring and the execution is placed in indefinite loop. Public Class Scheduler
Private configuration As SchedulerConfiguration = Nothing
Public Sub New(ByVal config As SchedulerConfiguration)
configuration = config
End Sub
Public Sub Start()
While True
Try
For Each job As ISchedulerJob In configuration.Jobs
job.Execute()
Next
Catch
Finally
Thread.Sleep(configuration.SleepInterval)
End Try
End While
End Sub
End Class
If you wish to execute the jobs only once at specific time, then simply do not use the while/wend loop and make sure you place a check if the current time (date.Now) is greater then scheduled time. In this case you may also wish to set scedule interval to seconds or minutes. That is all it takes to make the scheduler. To add a Jobs and execute them you need to do the following.
Private schedulerThread As System.Threading.Thread = Nothing
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Dim config As New MailScheduler.SchedulerConfiguration(60 * 60 * 1000)
config.Jobs.Add(New MailScheduler.MailJob())
config.Jobs.Add(New MailScheduler.OtherJob())
Dim scheduler As New MailScheduler.Scheduler(config)
Dim mailThreadStart As _
New System.Threading.ThreadStart(AddressOf scheduler.Start)
schedulerThread = New System.Threading.Thread(mailThreadStart)
schedulerThread.Start()
End Sub
Sub Application_End(ByVal sender As Object, ByVal e As EventArgs)
If Not IsNothing(schedulerThread) Then
schedulerThread.Abort()
End If
End Sub
I've placed the above code in the global.asax on application start with schedulerThread declared as private variable within the scope of global.asax. The reason is because I will need to reference it on application end to kill the same tread . That would be a perfect place or any scheduled task to run and then just continue to the site. Now as the site is working our jobs will execute in a separate thread that sleeps between the jobs executions for a specified period of time. If you wish the code to run as long as the asp.net worker process is alive leave the scheduler thread (do not abort it). IT IS DANGEROUS to leave any thread open, especially on hosting provider this may cause undesired results. So be WARNED. The safer method is to create public reference to the scheduler thread so you can reference it from within a page and abort it by simply loading the page (on page load event). The approach on how to start and kill the thread is up to you. This article intention was to give a simple code on implementing the scheduler functionality for recurring tasks. You may wish to search this site for more samples on creating safe threading models for your web site. Happy coding...
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||