Question

I am trying to schedule a task using Quartz.net 2.0 in ASP.NET MVC 4 application, but i can not get the task to be executed.

Here is the code:

public class ScheduleTaskConfig
{
    public static void StartScheduler()
    {
        ISchedulerFactory schedulerFactory = new StdSchedulerFactory();

        IScheduler scheduler = schedulerFactory.GetScheduler();

        JobKey emailSenderTaskKey = new JobKey("emailSenderTask", "email");
        IJobDetail emailSenderTask = JobBuilder.Create<QueuedEmailsSendTask>()
            .WithIdentity(emailSenderTaskKey)
            .Build();

        TriggerKey emailSenderTriggerKey = new TriggerKey("emailSenderTrigger", "email");
        ITrigger emailSenderTrigger = TriggerBuilder.Create()
            .WithIdentity(emailSenderTriggerKey)
            .WithSimpleSchedule(s => s.RepeatForever().WithIntervalInSeconds(5))
            .StartNow()
            .Build();

        scheduler.ScheduleJob(emailSenderTask, emailSenderTrigger);
        scheduler.Start();
    }
}

It is called in global.asax application start

protected void Application_Start()
{
    ScheduleTaskConfig.StartScheduler();
    ...
}

And here is the class that implements the IJob interface:

public class QueuedEmailsSendTask : IJob
{
    private IQueuedEmailsService _queuedEmailsService { get; set; }
    private IEmailSenderService _emailSenderService { get; set; }

    public QueuedEmailsSendTask(IQueuedEmailsService queuedEmailsService, IEmailSenderService emailSenderService)
    {
        this._queuedEmailsService = queuedEmailsService;
        this._emailSenderService = emailSenderService;
    }

    public void Execute(IJobExecutionContext executeContext)
    {
        //do stuff ...
    }
}

I placed a breakpoint at the beginning of the Execute method, but the debugger does not stop there. What am i doing wrong?

UPDATE: It has something to do with the class that implements the IJob interface not having a default constructor. It works, if I modify the constructor like this:

public QueuedEmailsSendTask()
{
}

But I need to be able to inject my dependencies. I am using the Autofac IoC container.

Was it helpful?

Solution

To make Quartz.net work with an IoC container you need to have a factory class implementing IJobFactory:

public class AutofacJobFactory : IJobFactory
{
    private readonly IContainer _container;

    public AutofacJobFactory(IContainer container)
    {
        _container = container;
    }

    public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        return (IJob)_container.Resolve(bundle.JobDetail.JobType);
    }
}

The JobFactory instance then needs to be assigned to the scheduler in the initialization code:

ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
IScheduler scheduler = schedulerFactory.GetScheduler();
scheduler.JobFactory = new AutofacJobFactory(container);

And don't forget to register the job in the IoC container.

OTHER TIPS

Have you tried scheduling the job after starting the scheduler?

public class ScheduleTaskConfig
{
    public static void StartScheduler()
    {
        ISchedulerFactory schedulerFactory = new StdSchedulerFactory();

        IScheduler scheduler = schedulerFactory.GetScheduler();
        scheduler.Start(); //start here   

        //construct job info

        scheduler.ScheduleJob(emailSenderTask, emailSenderTrigger); //schedule here
    }
}

You need to ensure that the AutofacJobFactory is responsible for instantiating the job. This means not using the JobBuilder object. Instead you should pass the details of the job to be created by the scheduler's AutofacJobFactory in the form of a JobDetailImpl object. Your working code would look something like the following.

ISchedulerFactory schedulerFactory = new StdSchedulerFactory();

IScheduler scheduler = schedulerFactory.GetScheduler();
scheduler.JobFactory = new AutofacJobFactory(container);
scheduler.Start(); //start here  

// construct job info
JobDetailImpl jobDetail = new JobDetailImpl("emailSenderTask", null, typeof(QueuedEmailsSendTask));

TriggerKey emailSenderTriggerKey = new TriggerKey("emailSenderTrigger", "email");
ITrigger emailSenderTrigger = TriggerBuilder.Create()
    .WithIdentity(emailSenderTriggerKey)
    .WithSimpleSchedule(s => s.RepeatForever().WithIntervalInSeconds(5))
    .StartNow()
    .Build();

sched.ScheduleJob(jobDetail, trigger);

For a complete example, please see the following question How do I create a Quartz.NET’s job requiring injection with autofac

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top