Brad Leach
Brad Leach

Reputation: 16997

How can I run Quartz.NET Jobs in a separate AppDomain?

Is it possible to run Quartz.NET jobs in a separate AppDomain? If so, how can this be achieved?

Upvotes: 6

Views: 1361

Answers (1)

Josh Gallagher
Josh Gallagher

Reputation: 5329

Disclaimer: I've not tried this, it's just an idea. And none of this code has been compiled, even.

Create a custom job factory that creates a wrapper for your real jobs. Have this wrapper implement the Execute method by creating a new app domain and running the original job in that app domain.

In more detail: Create a new type of job, say IsolatedJob : IJob. Have this job take as a constructor parameter the type of a job that it should encapsulate:

internal class IsolatedJob: IJob
{
    private readonly Type _jobType;

    public IsolatedJob(Type jobType)
    {
        _jobType = jobType ?? throw new ArgumentNullException(nameof(jobType));
    }

    public void Execute(IJobExecutionContext context)
    {
        // Create the job in the new app domain
        System.AppDomain domain = System.AppDomain.CreateDomain("Isolation");
        var job = (IJob)domain.CreateInstanceAndUnwrap("yourAssembly", _jobType.Name);
        job.Execute(context);
    }
}

You may need to create an implementation of IJobExecutionContext that inherits from MarshalByRefObject and proxies calls onto the original context object. Given the number of other objects that IJobExecutionContext provides access to, I'd be tempted to implement many members with a NotImplementedException as most won't be needed during job execution.

Next you need the custom job factory. This bit is easier:

internal class IsolatedJobFactory : IJobFactory
{
    public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        return NewJob(bundle.JobDetail.JobType);
    }

    private IJob NewJob(Type jobType)
    {
        return new IsolatedJob(jobType);
    }
}

Finally, you will need to instruct Quartz to use this job factory rather than the out of the box one. Use the IScheduler.JobFactory property setter and provide a new instance of IsolatedJobFactory.

Upvotes: 5

Related Questions