Using Quartz Scheduler In ASP.NET Core

Here, we will learn about using a Quartz scheduler in ASP.NET Core. The scheduler is very useful for running tasks in the background. For example, we have to write in a file every 5 min, so the simplest method will be to create a schedule to write in a file. so that it can be called at every 5 min.

Prerequisites:

  • Basic knowledge of ASP.NET Core and C#

Create a new project in ASP.NET Core.

Open the Package Manager Console and type the following command in it.

Install-Package Quartz

Create a new folder namely “Schedulers”. you can use your own name.

Now, inside this “Schedulers” folder create a new class namely “JobSchedule”, and paste the below code there.

using System;

namespace Faisal.Schedulers
{
    public class JobSchedule
    {
        public JobSchedule(Type jobType, string cronExpression)
        {
            JobType = jobType;
            CronExpression = cronExpression;
        }

        public Type JobType { get; }
        public string CronExpression { get; }
    }
}

inside the same “Schedulers” folder create a new class namely “QuartzHostedService” which inherits from “IHostedService”, and paste the below code there.

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Quartz;
using Quartz.Spi;

namespace Faisal.Schedulers
{
    public class QuartzHostedService : IHostedService
    {
        private readonly ISchedulerFactory _schedulerFactory;
        private readonly IJobFactory _jobFactory;
        private readonly IEnumerable<JobSchedule> _jobSchedules;

        public QuartzHostedService(
            ISchedulerFactory schedulerFactory,
            IJobFactory jobFactory,
            IEnumerable<JobSchedule> jobSchedules)
        {
            _schedulerFactory = schedulerFactory;
            _jobSchedules = jobSchedules;
            _jobFactory = jobFactory;
        }
        public IScheduler Scheduler { get; set; }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            Scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
            Scheduler.JobFactory = _jobFactory;

            foreach (var jobSchedule in _jobSchedules)
            {
                var job = CreateJob(jobSchedule);
                var trigger = CreateTrigger(jobSchedule);

                await Scheduler.ScheduleJob(job, trigger, cancellationToken);
            }

            await Scheduler.Start(cancellationToken);
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            await Scheduler?.Shutdown(cancellationToken);
        }

        private static IJobDetail CreateJob(JobSchedule schedule)
        {
            var jobType = schedule.JobType;
            return JobBuilder
                .Create(jobType)
                .WithIdentity(jobType.FullName)
                .WithDescription(jobType.Name)
                .Build();
        }

        private static ITrigger CreateTrigger(JobSchedule schedule)
        {
            return TriggerBuilder
                .Create()
                .WithIdentity($"{schedule.JobType.FullName}.trigger")
                .WithCronSchedule(schedule.CronExpression)
                .WithDescription(schedule.CronExpression)
                .Build();
        }
    }
}

Create a new class namely “SingletonJobFactory” inside the same folder, and copy the below code and paste inside that file.

using Microsoft.Extensions.DependencyInjection;
using Quartz;
using Quartz.Spi;
using System;

namespace Faisal.Schedulers
{
    public class SingletonJobFactory : IJobFactory
    {
        private readonly IServiceProvider _serviceProvider;
        public SingletonJobFactory(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            return _serviceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
        }

        public void ReturnJob(IJob job) { }
    }
}

Now we have done with Quartz setup files, Now let’s create a new class to call/schedule our code. To do that create new class anywhere. I’ll use the same folder and will give class name as “RemindersJob”, which inherits from “IJob” interface.

The below code will execute the as per scheduler time which we will set in startup class. You need to write your own code which you want to execute in the scheduler.

Below is my “RemindersJob” class code. which write in files at every 5 minutes.

using Quartz;
using System;
using System.IO;
using System.Threading.Tasks;

namespace Faisal.Schedulers
{
    public class RemindersJob : IJob
    {
        private readonly IServiceProvider _provider;
        private readonly IEmailSender _emailSender;
        public RemindersJob(IServiceProvider provider, IEmailSender emailSender)
        {
            _provider = provider;
            _emailSender = emailSender;
        }

        public Task Execute(IJobExecutionContext context)
        {
            Logs($"{DateTime.Now} [Reminders Service called]" + Environment.NewLine);
            
            return Task.CompletedTask;
        }      
        public void Logs(string message)
        {
            var path = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Quartz");
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            path = Path.Combine(path, "Logs.txt");
            using FileStream fstream = new FileStream(path, FileMode.Create);
            using TextWriter writer = new StreamWriter(fstream);
            writer.WriteLine(message);
        }
    }
}

We have done all code. now we just need to set a timer for service, for that, we need to add the below code in the startup class inside the “ConfigureServices” method.

// Add Quartz services
services.AddHostedService<QuartzHostedService>();
services.AddSingleton<IJobFactory, SingletonJobFactory>();
services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();

// Add our job
services.AddSingleton<RemindersJob>();
services.AddSingleton(new JobSchedule(
    jobType: typeof(RemindersJob),
    cronExpression: "0 0/5 * 1/1 * ? *")); // run every 5 min

Vision Infotech‘s team of ASP.NET developers is capable of developing powerful and dynamic ASP.NET applications. Hire .NET developers from our team to incorporate cutting-edge technologies into your web or mobile apps. Hire ASP.NET developers if you need custom development, such as a custom framework or APIs. Our Dedicated ASP.NET Developers & Programmers can collaborate with you to create strong web apps that add value to your company.

4 Comments

  1. Atul Singhal

    Thanks you Faisal to share the Quartz tutorial. But I’m unable work on below points. If you give your precious time on this it’ll be very helpful.

    1. How to fetch value from appsettings.json file
    2. Add Cron expression dynamically in scheduler key wise
    3. How to run multiple jobs simultaneously using the same code flow

    0
    0
    Reply
  2. Letskaliuk Andrii

    Thank You Faisal. It’s very useful article about how to use Quartz. Hello from Ukraine (Слава Україні)
    Best regards.
    StdSchedulerFactory – don’t need to do this. First three rows are Quartz services – as author wrote.

    0
    0
    Reply
  3. Mehdi

    Great job,

    but just what StdSchedulerFactory woyld be replaced with in services.AddSingleton(); ?

    Thanks

    0
    0
    Reply
  4. Faisal M

    perfect job man. You are the best. This article helped me to implement the background task and run the same job multiple times with different cron expressions, which i have been trying for many days with different solutions and none of them solved my problem.
    Thank you.

    0
    0
    Reply

Submit a Comment

Your email address will not be published. Required fields are marked *

Subscribe

Select Categories