我需要从 JSON 文件读取 Quartz 作业配置并使用特定作业模板(配置触发器和 IJobDetail)生成作业实例。这是动态创建作业的代码:
public class JobRunner
{
private readonly IConfiguration _configuration;
private readonly ISchedulerFactory _jobSchedularFactory;
private readonly IJobFactory _jobFactory;
public JobRunner(IConfiguration configuration, ISchedulerFactory jobSchedularFactory, IJobFactory jobFactory)
{
_configuration = configuration;
_jobSchedularFactory = jobSchedularFactory;
_jobFactory = jobFactory;
}
public async Task StartAsync()
{
IScheduler scheduler=await _jobSchedularFactory.GetScheduler();
scheduler.JobFactory=_jobFactory;
await CreateJob(scheduler);
}
private async Task CreateJob(IScheduler scheduler)
{
var jobs= _configuration.GetSection("Jobs").Get<List<JobOptions>>()??new ();
foreach (var item in jobs)
{
if (!item.Enabled)
{
continue;
}
var jobData=new JobDataMap();
jobData.Add("LineId",item.LineId);
jobData.Add("DataSourceName",item.DataSourceName);
IJobDetail job=JobBuilder.Create<DemoJob>()
.WithIdentity(item.LineId!)
.SetJobData(jobData)
.Build();
ITrigger trigger=TriggerBuilder.Create()
.WithIdentity(item.LineId)
.WithCronSchedule(item.Corn)
.Build();
await scheduler.ScheduleJob(job,trigger);
await scheduler.Start();
}
}
}
模块中的配置如下:
[DependsOn(
typeof(AbpQuartzModule)
)]
public class BackJobWorkerModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var config= context.Services.GetConfiguration();
context.Services.AddSingleton<IConfiguration>(config);
context.Services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
context.Services.AddSingleton<IJobFactory, LineJobFactory>();
context.Services.AddSingleton<JobRunner>();
}
/// <inheritdoc />
public override async Task OnPostApplicationInitializationAsync(ApplicationInitializationContext context)
{
await base.OnPostApplicationInitializationAsync(context);
var runner = context.ServiceProvider.GetRequiredService<JobRunner>();
await runner.StartAsync();
}
}
运行器正确使用配置文件中配置的作业JSON信息来生成作业实例,并实现了自定义的JobFactory。作业模板代码是从容器中提取的。一切运行顺利,但是当尝试使用EF Core访问数据库时,出现了无法访问已处置的DbContext的错误。使用UnitOfWorkAttribute没有任何效果;仅手动使用 UnitOfWorkManager.Begin 才能正常工作。还有其他方法可以解决这个问题吗?
我搜索了相关文档和论坛,但没有找到好的解决方案。
使其成为
virtual
方法:
[UnitOfWork]
public virtual async Task Execute(IJobExecutionContext context)
{
// ...
}
来自 https://docs.abp.io/en/abp/8.1/Unit-Of-Work:
- 如果您不是通过接口注入服务(如
),那么服务的方法必须是IMyService
(否则,动态代理/拦截系统无法工作)。virtual