简体   繁体   English

Quartz.NET JobBuilder.Create<> 重用相同的 IJob 实例

[英]Quartz.NET JobBuilder.Create<> reuses same instance of IJob

I would like to have new instance of IJob for every execution.我想为每次执行都有新的 IJob 实例。 Here is how I have job setup:这是我的工作设置:

[Export(typeof(IJob))]
[PartCreationPolicy(CreationPolicy.NonShared)]
[DisallowConcurrentExecution]
public class TestProcessor : IJob
{
    [Import]
    public ILoggerService LoggerService { get; set; }
    
    private string InstanceId { get; }

    public TestProcessor()
    {
        this.InstanceId = Guid.NewGuid().ToString().Substring(0, 4);
    }

    public void Execute(IJobExecutionContext context)
    {        
        // TODO: Here I expect to see log entry with different InstanceId every time
        string processGroupId = null;
        if (context != null && context.MergedJobDataMap.ContainsKey(JobListener.ProcessGroupId))
            processGroupId = context.MergedJobDataMap[JobListener.ProcessGroupId].ToString();

        this.LoggerService.Log(null, $"TEST: Group: {processGroupId}, JobInstance: {this.InstanceId}, ServiceInstance: {this.FuelPriceService.InstanceId}", Category.Debug, Priority.Low);
                
    }
}

Here is how I schedule this job for execution.以下是我如何安排执行此作业。 Idea here, to run concurrent executions for different "groups" so those instances run on same schedule.这里的想法是为不同的“组”运行并发执行,以便这些实例按相同的时间表运行。 But I see same instance Id in all Logs for all groups但我在所有组的所有日志中看到相同的实例 ID

foreach (var pgId in processGroups)
{    
    // Test Processor
    var testJobDetail = JobBuilder.Create<TestProcessor>().Build();
    testJobDetail.JobDataMap.Add(JobListener.ProcessGroupId, pgId);
    testJobDetail.JobDataMap.Add(JobListener.TimeLimitSeconds, "300");
    
    this.scheduler.ScheduleJob(testJobDetail, TriggerBuilder.Create().WithCronSchedule("0 0/5 * * * ?").Build());
}

I am not sure how我不确定如何

JobBuilder.Create<>() JobBuilder.创建<>()

works.作品。 It seems to ignore MEF attribute and uses its own container?它似乎忽略了 MEF 属性并使用了自己的容器? I expect to have new instance every time I run JobBuilder.Create<> but not seeing it.我希望每次运行 JobBuilder.Create<> 但看不到它时都有新实例。

EDIT : More details编辑:更多细节

Code runs inside windows service project.代码在 windows 服务项目中运行。 Inside ServiceBase constructor following code executed.在执行代码后的 ServiceBase 构造函数中。 After those objects created I schedule jobs like shown above.创建这些对象后,我安排了如上所示的作业。 Qauartz.JobBuilder used to create them (not custom one). Qauartz.JobBuilder 用于创建它们(不是自定义的)。 There is no other code, specifically nothing about configuring MEF for Quartz.没有其他代码,特别是没有关于为 Quartz 配置 MEF 的代码。

// Import job factory 
var jobFactoryInstance = Bootstrapper.CompositionContainer.GetExports<IJobFactory>().FirstOrDefault();
if (jobFactoryInstance == null) throw new InvalidOperationException("Job Factory instance wasn't created!");
var jobFactory = jobFactoryInstance.Value;

// construct a scheduler factory
ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
this.scheduler = schedulerFactory.GetScheduler();
this.scheduler.JobFactory = jobFactory;

// Import job listener
var jobListenerInstance = Bootstrapper.CompositionContainer.GetExports<IJobListener>().FirstOrDefault();
if (jobListenerInstance == null) throw new InvalidOperationException();
var jobListener = jobListenerInstance.Value;
this.scheduler.ListenerManager.AddJobListener(jobListener, EverythingMatcher<JobKey>.AllJobs());

EDIT2 : Job factory details, this is only place that manually instantiated. EDIT2 :作业工厂详细信息,这只是手动实例化的地方。 Looks like this is where I need to provide fix by manually creating instance instead of using pre-imported list?看起来这是我需要通过手动创建实例而不是使用预导入列表来提供修复的地方? Sounds like I am answering my q..听起来我正在回答我的问题..

[Export(typeof(IJobFactory))]
public class JobFactory : IJobFactory
{
    [ImportMany(typeof(IJob))]
    public List<IJob> Jobs { get; private set; }

    public virtual IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
    {
        try
        {
            Debug.WriteLine("IDATT.WindowsService.JobFactory - getting job from a list");
            return this.Jobs.First(j => j.GetType() == bundle.JobDetail.JobType);
        }
        catch (Exception e)
        {
            var se = new SchedulerException(string.Format(CultureInfo.InvariantCulture, "Problem instantiating class '{0}'", bundle.JobDetail.JobType.FullName), e);
            throw se;
        }
    }

    public virtual void ReturnJob(IJob job)
    {
    }
}

As you already found - you have custom JobBuilder which is responsible for creating new job instances.正如您已经发现的那样 - 您有自定义JobBuilder负责创建新的作业实例。 In that builder you have static list of job instances ( List<IJob> Jobs ) imported from MEF, and then you getting an instance from that list based on requested JobType .在该构建器中,您有 static 个从 MEF 导入的作业实例列表 ( List<IJob> Jobs ),然后您根据请求的JobType从该列表中获取一个实例。 So in result you indeed explicitly made it so that single instance of TestProcessor is being returned every time.因此,结果您确实明确地做到了,以便每次都返回TestProcessor的单个实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM