如何通过API和端点动态创建Quartz.Net任务调度器
Quartz.Net 动态任务管理实现方案
核心结论
Quartz.Net 完全支持运行时动态创建、管理任务,绝对不局限于在Program.cs中初始化配置,完全适配你描述的从数据库加载初始任务、API动态新增任务的场景。
实现步骤与关键代码
1. 应用启动时加载数据库初始任务
在应用启动完成后,读取ScheduledTasks表数据,逐个创建Job和Trigger并加入调度器,推荐用IHostedService来实现启动加载逻辑:
public class TaskLoaderHostedService : IHostedService { private readonly IScheduler _scheduler; private readonly YourDbContext _dbContext; public TaskLoaderHostedService(IScheduler scheduler, YourDbContext dbContext) { _scheduler = scheduler; _dbContext = dbContext; } public async Task StartAsync(CancellationToken cancellationToken) { await _scheduler.Start(cancellationToken); // 读取数据库中所有待调度任务 var tasks = await _dbContext.ScheduledTasks.ToListAsync(cancellationToken); foreach (var task in tasks) { // 构建Job详情,绑定自定义Job类型 var jobDetail = JobBuilder.Create<YourCustomJob>() .WithIdentity(task.TaskId.ToString(), task.TaskGroup) .UsingJobData("TaskParam", task.TaskParam) // 传递任务参数 .Build(); // 构建Trigger,使用数据库存储的Cron表达式 var trigger = TriggerBuilder.Create() .WithIdentity($"trigger_{task.TaskId}", task.TaskGroup) .WithCronSchedule(task.CronExpression) .Build(); // 将任务加入调度器 await _scheduler.ScheduleJob(jobDetail, trigger, cancellationToken); } } public async Task StopAsync(CancellationToken cancellationToken) { await _scheduler.Shutdown(cancellationToken); } }
然后在Program.cs中注册这个HostedService:
builder.Services.AddHostedService<TaskLoaderHostedService>();
2. API调用时动态新增任务
创建API接口,先将用户提交的任务信息写入数据库,再创建对应的Job和Trigger加入调度器:
[ApiController] [Route("api/scheduled-tasks")] public class ScheduledTasksController : ControllerBase { private readonly IScheduler _scheduler; private readonly YourDbContext _dbContext; public ScheduledTasksController(IScheduler scheduler, YourDbContext dbContext) { _scheduler = scheduler; _dbContext = dbContext; } [HttpPost] public async Task<IActionResult> AddNewTask([FromBody] NewTaskRequest request) { // 1. 写入数据库 var dbTask = new ScheduledTask { TaskGroup = request.TaskGroup, CronExpression = request.CronExpression, TaskParam = request.TaskParam, // 填充其他必要字段 }; _dbContext.ScheduledTasks.Add(dbTask); await _dbContext.SaveChangesAsync(); // 2. 创建并调度任务 var jobDetail = JobBuilder.Create<YourCustomJob>() .WithIdentity(dbTask.TaskId.ToString(), dbTask.TaskGroup) .UsingJobData("TaskParam", dbTask.TaskParam) .Build(); var trigger = TriggerBuilder.Create() .WithIdentity($"trigger_{dbTask.TaskId}", dbTask.TaskGroup) .WithCronSchedule(dbTask.CronExpression) .Build(); await _scheduler.ScheduleJob(jobDetail, trigger); return Ok(new { TaskId = dbTask.TaskId }); } }
3. 关键注意事项
- 自定义Job类型:必须实现
IJob接口,在Execute方法中编写具体的任务逻辑,比如:public class YourCustomJob : IJob { public async Task Execute(IJobExecutionContext context) { var taskParam = context.JobDetail.JobDataMap.GetString("TaskParam"); // 执行任务逻辑 await Task.CompletedTask; } } - 唯一性保障:用数据库的
TaskId作为Job和Trigger的标识,避免重复调度。 - 异常处理:在加载和创建任务时添加异常捕获,防止单个任务失败影响整体流程。
- 状态持久化:如果需要Quartz自身维护任务运行状态,可以配置ADO.NET JobStore;如果依赖自己的数据库,只需在应用重启时重新加载即可。
内容的提问来源于stack exchange,提问作者CrystalBlue
相关产品推荐
相关产品推荐

