Azure Worker Role With Quartz.NET

In this article, I will be explaining the usage of Azure Worker Role along with Quartz.NET and a practical example showing 3 different jobs running under the same worker role.

What is Azure Worker Role?

"The WorkerRole element describes a role that is useful for generalized development and may perform background processing for a web role. A service may contain zero or more worker roles." Read more here.

What is Quartz.NET?

 "Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large-scale enterprise systems." Read more here.

Quartz.NET Key Features 
  • Job schedulling
  • Job Persistence
  • Clustering
  • Job Execution
Read more about it's features here
 
What are the benefits of using Azure Worker Role + Quartz.Net ? 
  • Schedule jobs to run in a certain period of time, saving processing hours. (and money)
  • Schedule more than one job to run in the same instance and much more..
  • Check Azure Pricing here.
  • Check Quartz.Net schedulling options here.  
Need help to create your database?
  • Check how to create your local database here.
  • Check how to create your Azure database here.
NuGet Packages required,
  • EntityFramework (database access) 
  • Quartz
How to do it?

Create the project as a cloud service project, with the worker role as following.
 
Azure Worker Role With Quartz.Net
 
 Azure Worker Role With Quartz.Net
 
You are going to have two projects in your solution, pay attention in the current project when installing the NuGet Packages.
 
Azure Worker Role With Quartz.Net 
 
These are the jobs that are going to be used here, do not forget that they must inherit from IJob.
  1. public class JobSampleOne : IJob  
  2. {  
  3.     private BusinessSample _business;  
  4.   
  5.     public JobSampleOne()  
  6.     {  
  7.         _business = new BusinessSample( this.GetType().ToString() );  
  8.     }  
  9.   
  10.     public Task Execute( IJobExecutionContext context )  
  11.     {  
  12.         return _business.Ping();  
  13.     }  
  14. }  
  1. public class JobSampleTwo : IJob  
  2.   {  
  3.       private BusinessSample _business;  
  4.   
  5.       public JobSampleTwo()  
  6.       {  
  7.           _business = new BusinessSample( this.GetType().ToString() );  
  8.       }  
  9.   
  10.       public async Task Execute( IJobExecutionContext context )  
  11.       {  
  12.           await _business.Ping();  
  13.       }  
  14.   }  
  1. public class JobSampleThree : IJob  
  2.  {  
  3.      private BusinessSample _business;  
  4.   
  5.      public JobSampleThree()  
  6.      {  
  7.          _business = new BusinessSample( this.GetType().ToString() );  
  8.      }  
  9.   
  10.      public async Task Execute( IJobExecutionContext context )  
  11.      {  
  12.          await _business.Ping();  
  13.      }  
  14.  }  
This is the business class definition.
  1. public class BusinessSample  
  2.     {  
  3.         private string _jobName;  
  4.         private SampleContext _sampleContext;  
  5.   
  6.         public BusinessSample( string jobName )  
  7.         {  
  8.             _jobName = jobName;  
  9.             _sampleContext = new SampleContext();  
  10.         }  
  11.   
  12.         public Task Ping()  
  13.         {  
  14.             _sampleContext.LogSample.Add( new LogSample  
  15.             {  
  16.                 JobName = _jobName,  
  17.                 LogDate = DateTime.Now  
  18.             } );  
  19.             return  
  20.               _sampleContext.SaveChangesAsync();  
  21.         }  
  22.     }   
Now, let's schedule these jobs to run in different timing.
  1. public class WorkerRole : RoleEntryPoint  
  2.     {  
  3.         private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();  
  4.         private readonly ManualResetEvent runCompleteEvent = new ManualResetEvent( false );  
  5.         private IScheduler scheduler;  
  6.   
  7.         public override void Run()  
  8.         {  
  9.             Trace.TraceInformation( "WorkerRoleSample is running" );  
  10.   
  11.             try  
  12.             {  
  13.                 this.RunAsync( this.cancellationTokenSource.Token ).Wait();  
  14.             }  
  15.             finally  
  16.             {  
  17.                 this.runCompleteEvent.Set();  
  18.             }  
  19.         }  
  20.   
  21.         private void ConfigureScheduler()  
  22.         {  
  23.             var scheduleFactory = new StdSchedulerFactory();  
  24.             scheduler = scheduleFactory.GetScheduler().Result;  
  25.   
  26.             IJobDetail job = new JobDetailImpl( "Sample1"typeof( JobSampleOne ) );  
  27.             IJobDetail jobTwo = new JobDetailImpl( "Sample2"typeof( JobSampleTwo ) );  
  28.             IJobDetail jobThree = new JobDetailImpl( "Sample3"typeof( JobSampleThree ) );  
  29.             ITrigger trigger = TriggerBuilder.Create()  
  30.                 .WithSchedule( SimpleScheduleBuilder.RepeatMinutelyForever( 10 ) )  
  31.                    .StartAt( DateTime.Now.AddMinutes( 1 ) )  
  32.                    .Build();  
  33.             ITrigger triggerTwo = TriggerBuilder.Create()  
  34.                 .WithSchedule( SimpleScheduleBuilder.RepeatMinutelyForever( 6 ) )  
  35.                    .StartAt( DateTime.Now.AddMinutes( 4 ) )  
  36.                    .Build();  
  37.             ITrigger triggerThree = TriggerBuilder.Create()  
  38.                 .WithSchedule( SimpleScheduleBuilder.RepeatMinutelyForever( 8 ) )  
  39.                    .StartAt( DateTime.Now.AddMinutes( 7 ) )  
  40.                    .Build();  
  41.   
  42.             scheduler.ScheduleJob( job, trigger );  
  43.             scheduler.ScheduleJob( jobTwo, triggerTwo );  
  44.             scheduler.ScheduleJob( jobThree, triggerThree );  
  45.   
  46.             scheduler.Start();  
  47.         }  
  48.   
  49.         public override bool OnStart()  
  50.         {  
  51.             // Set the maximum number of concurrent connections  
  52.             ServicePointManager.DefaultConnectionLimit = 12;  
  53.   
  54.             // For information on handling configuration changes  
  55.             // see the MSDN topic at https://go.microsoft.com/fwlink/?LinkId=166357.  
  56.   
  57.             bool result = base.OnStart();  
  58.             ConfigureScheduler();  
  59.             Trace.TraceInformation( "WorkerRoleSample has been started" );  
  60.   
  61.             return result;  
  62.         }  
  63.   
  64.         public override void OnStop()  
  65.         {  
  66.             Trace.TraceInformation( "WorkerRoleSample is stopping" );  
  67.   
  68.             this.cancellationTokenSource.Cancel();  
  69.             this.runCompleteEvent.WaitOne();  
  70.   
  71.             base.OnStop();  
  72.   
  73.             Trace.TraceInformation( "WorkerRoleSample has stopped" );  
  74.         }  
  75.   
  76.         private async Task RunAsync( CancellationToken cancellationToken )  
  77.         {  
  78.             // TODO: Replace the following with your own logic.  
  79.             while ( !cancellationToken.IsCancellationRequested )  
  80.             {  
  81.                 Trace.TraceInformation( "Working" );  
  82.                 await Task.Delay( 1000 );  
  83.             }  
  84.         }  
  85.     }  
You can see that the first job is going to run after 1 minute of its deployment and then for each 10 minutes. The second job is going to run after 4 minutes of its deployment and then for each 6 minutes. The third job is going to run after 7 minutes of its deployment and after that, for each 8 minutes. 
 
Here, we have the result of the worker role execution for 30 minutes.

Azure Worker Role With Quartz.Net
 
If you do not know how to publish, you have two options,
Congratulations, you have successfully set up your Azure Worker Role to run along with Quartz.NET.