Quartz.NET JobBuilder复用IJob实例:如何每次执行生成新实例?
问题分析与解决方案
问题根源
你的JobFactory通过[ImportMany(typeof(IJob))]预加载了所有Job实例,MEF在导入这个列表时,会为每个Job类型创建一次实例并存入列表。后续Quartz每次执行Job时,NewJob方法只是从列表中取出已有的实例返回,完全忽略了TestProcessor上[PartCreationPolicy(CreationPolicy.NonShared)]的配置,导致所有Job执行都复用同一个实例,InstanceId自然不会变化。
解决方案
修改JobFactory,放弃预存Job实例列表,改为直接从MEF容器中每次创建新实例,这样就能遵循NonShared的创建策略,实现每次Job执行都生成新实例的需求。
修改后的JobFactory代码:
[Export(typeof(IJobFactory))] public class JobFactory : IJobFactory { [Import] public CompositionContainer Container { get; set; } public virtual IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) { try { Debug.WriteLine("IDATT.WindowsService.JobFactory - creating new job instance from container"); // 从MEF容器中获取新的Job实例,遵循NonShared创建策略 return Container.GetExportedValue<IJob>(bundle.JobDetail.JobType.FullName); } 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) { // 若Job实现了IDisposable,可在此释放资源 if (job is IDisposable disposableJob) { Container.ReleaseExport(disposableJob); } } }
补充说明
- 保留
TestProcessor上的[PartCreationPolicy(CreationPolicy.NonShared)]属性,MEF会依据该策略每次创建新实例; - 原有调度代码无需修改,Quartz每次触发Job时都会调用
NewJob获取新实例,日志中的InstanceId将每次都不同。
内容的提问来源于stack exchange,提问作者katit
相关产品推荐
相关产品推荐

