You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ASP.NET 6.0运行时动态调度Quartz.Net作业

实现ASP.NET Core 6.0运行时管理Quartz.Net作业触发器的方案

一、基础DI整合配置

先完成Quartz.Net与ASP.NET Core的依赖注入整合,在Program.cs中初始化核心组件,不硬编码具体任务:

builder.Services.AddQuartz(q =>
{
    // 让作业能通过DI获取服务实例
    q.UseMicrosoftDependencyInjectionJobFactory();
    // 配置SQLite持久化(适配树莓派轻量场景,避免重启丢失任务)
    q.UsePersistentStore(s =>
    {
        s.UseSqlite("Data Source=quartz.db");
        s.UseJsonSerializer();
    });
});

// 注册Quartz后台服务,确保任务持续运行
builder.Services.AddQuartzServer(options =>
{
    options.WaitForJobsToComplete = true;
});

二、构建参数模型与Cron转换逻辑

  1. 定义接收前端参数的模型:
public class JobTriggerRequest
{
    public string JobName { get; set; }
    public string JobGroup { get; set; }
    public int[] SelectedWeekDays { get; set; } // 前端传入:1=周一,7=周日
    public TimeSpan TriggerTime { get; set; }
    public string JobDescription { get; set; }
}
  1. 实现星期+时间转Cron表达式的逻辑(注意Quartz周字段规则:1=周日,2=周一…7=周六,需做映射):
private string GenerateCronExpression(TimeSpan time, int[] weekDays)
{
    // 把前端的周一(1)映射为Quartz的2,以此类推
    var mappedWeekDays = weekDays.Select(d => d + 1);
    var weekDayStr = string.Join(",", mappedWeekDays);
    // Cron格式:秒 分 时 日 月 周 年(可选),日字段用?避免与周字段冲突
    return $"{time.Second} {time.Minute} {time.Hours} ? * {weekDayStr}";
}

三、控制器中实现运行时作业管理

直接在控制器注入IScheduler,编写添加、更新、删除作业的接口:

[ApiController]
[Route("api/job")]
public class JobController : ControllerBase
{
    private readonly IScheduler _scheduler;

    public JobController(IScheduler scheduler)
    {
        _scheduler = scheduler;
    }

    // 添加新作业
    [HttpPost("add")]
    public async Task<IActionResult> AddJob([FromBody] JobTriggerRequest request)
    {
        // 构建作业详情(假设你的继电器控制作业类为RelayControlJob)
        var jobDetail = JobBuilder.Create<RelayControlJob>()
            .WithIdentity(request.JobName, request.JobGroup)
            .WithDescription(request.JobDescription)
            .Build();

        // 生成Cron触发器
        var cronExpr = GenerateCronExpression(request.TriggerTime, request.SelectedWeekDays);
        var trigger = TriggerBuilder.Create()
            .WithIdentity($"{request.JobName}-trigger", request.JobGroup)
            .WithCronSchedule(cronExpr)
            .Build();

        // 提交调度
        await _scheduler.ScheduleJob(jobDetail, trigger);
        return Ok("作业已添加");
    }

    // 更新现有触发器
    [HttpPost("update")]
    public async Task<IActionResult> UpdateTrigger([FromBody] JobTriggerRequest request)
    {
        var triggerKey = new TriggerKey($"{request.JobName}-trigger", request.JobGroup);
        var existingTrigger = await _scheduler.GetTrigger(triggerKey);
        
        if (existingTrigger == null)
            return NotFound("触发器不存在");

        // 生成新Cron规则并更新触发器
        var cronExpr = GenerateCronExpression(request.TriggerTime, request.SelectedWeekDays);
        var newTrigger = existingTrigger.GetTriggerBuilder()
            .WithCronSchedule(cronExpr)
            .Build();

        await _scheduler.RescheduleJob(triggerKey, newTrigger);
        return Ok("触发器已更新");
    }

    // 删除作业
    [HttpDelete("remove")]
    public async Task<IActionResult> RemoveJob(string jobName, string jobGroup)
    {
        var jobKey = new JobKey(jobName, jobGroup);
        var result = await _scheduler.DeleteJob(jobKey);
        return result ? Ok("作业已删除") : NotFound("作业不存在");
    }

    // Cron表达式生成方法
    private string GenerateCronExpression(TimeSpan time, int[] weekDays)
    {
        var mappedWeekDays = weekDays.Select(d => d + 1);
        var weekDayStr = string.Join(",", mappedWeekDays);
        return $"{time.Second} {time.Minute} {time.Hours} ? * {weekDayStr}";
    }
}

四、作业类实现(以继电器控制为例)

编写具体的作业逻辑类,通过DI注入设备操作服务:

public class RelayControlJob : IJob
{
    private readonly IRelayService _relayService;

    // 依赖注入设备服务
    public RelayControlJob(IRelayService relayService)
    {
        _relayService = relayService;
    }

    public async Task Execute(IJobExecutionContext context)
    {
        // 执行继电器控制逻辑,比如开关切换
        await _relayService.ToggleRelay();
    }
}

记得将IRelayService及其实现类注册到DI容器中。

五、前端闹钟式界面实现

用简单的HTML+JS构建作业配置表单,提交数据到后端接口:

<form id="jobForm">
    <div>
        <label>作业名称:</label>
        <input type="text" name="jobName" required>
    </div>
    <div>
        <label>作业分组:</label>
        <input type="text" name="jobGroup" value="RelayJobs">
    </div>
    <div>
        <label>选择星期:</label>
        <input type="checkbox" name="weekDays" value="1">周一
        <input type="checkbox" name="weekDays" value="2">周二
        <input type="checkbox" name="weekDays" value="3">周三
        <input type="checkbox" name="weekDays" value="4">周四
        <input type="checkbox" name="weekDays" value="5">周五
        <input type="checkbox" name="weekDays" value="6">周六
        <input type="checkbox" name="weekDays" value="7">周日
    </div>
    <div>
        <label>触发时间:</label>
        <input type="time" name="triggerTime" required>
    </div>
    <div>
        <label>作业描述:</label>
        <textarea name="jobDescription"></textarea>
    </div>
    <button type="submit">添加作业</button>
</form>

<script>
document.getElementById('jobForm').addEventListener('submit', async (e) => {
    e.preventDefault();
    const formData = new FormData(e.target);
    const weekDays = Array.from(formData.getAll('weekDays')).map(Number);
    const timeParts = formData.get('triggerTime').split(':');
    
    const requestData = {
        jobName: formData.get('jobName'),
        jobGroup: formData.get('jobGroup'),
        selectedWeekDays: weekDays,
        triggerTime: {
            hours: parseInt(timeParts[0]),
            minutes: parseInt(timeParts[1]),
            seconds: 0
        },
        jobDescription: formData.get('jobDescription')
    };

    const response = await fetch('/api/job/add', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(requestData)
    });

    alert(await response.text());
});
</script>

六、树莓派部署注意事项

  • 发布时选择.NET 6的linux-arm或linux-arm64架构,适配树莓派硬件
  • 用SQLite持久化无需额外安装数据库,轻量易维护
  • 将程序注册为系统服务,确保树莓派开机自动启动作业调度服务

内容的提问来源于stack exchange,提问作者oglcn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 22:12:55