Skip to content
导航目录

任务调度

配置任务调度

在 MyCompanyName.MyProjectName.Host\Program.cs 文件配置任务调度

cs
using MyCompanyName.MyProjectName.Api.Core.Handlers;
using FreeScheduler;
using ZhonTai.Admin.Core;
using ZhonTai.Admin.Core.Startup;
using ZhonTai.Admin.Tools.TaskScheduler;

new HostApp(new HostAppOptions()
{
    //配置FreeSql
    ConfigureFreeSql = (freeSql, dbConfig) =>
    {
        if (dbConfig.Key == DbKeys.AppDb)
        {
            freeSql.SyncSchedulerStructure(dbConfig, (fsql) =>
            {
                fsql.CodeFirst
                .ConfigEntity<TaskInfo>(a =>
                {
                    a.Name("app_task");
                })
                .ConfigEntity<TaskLog>(a =>
                {
                    a.Name("app_task_log");
                });
            });
        }
    },

	//配置后置服务
	ConfigurePostServices = context =>
	{
		//添加任务调度,默认使用当前主库作为任务调度数据库
        //可通过AddTaskScheduler(DbKeys.AppDb, options => {})数据库键参数修改任务调度数据库
		context.Services.AddTaskScheduler(options =>
		{
			options.ConfigureFreeSql = freeSql =>
			{
				freeSql.CodeFirst
				//配置任务表
				.ConfigEntity<TaskInfo>(a =>
				{
					a.Name("app_task");
				})
				//配置任务日志表
				.ConfigEntity<TaskLog>(a =>
				{
					a.Name("app_task_log");
				});
			};

			//模块任务处理器
            options.TaskHandler = new CloudTaskHandler(options.FreeSqlCloud, DbKeys.AppDb);
            //模块自定义任务处理器,解析cron表达式
            options.CustomTaskHandler = new AppCustomTaskHandler();
		});
	},
	//配置后置中间件
	ConfigurePostMiddleware = context =>
	{
		var app = context.App;

		//使用任务调度
		app.UseTaskScheduler();
	}
}).Run(args);

public partial class Program { }

更多任务表和任务日志表配置

cs
freeSql.CodeFirst
//配置任务表
.ConfigEntity<TaskInfo>(a =>
{
    a.Name("app_task");
    a.Property((TaskInfo b) => b.Id).IsPrimary(value: true);
    a.Property((TaskInfo b) => b.Body).StringLength(-1);
    a.Property((TaskInfo b) => b.Interval).MapType(typeof(int));
    a.Property((TaskInfo b) => b.IntervalArgument).StringLength(1024);
    a.Property((TaskInfo b) => b.Status).MapType(typeof(int));
    a.Property((TaskInfo b) => b.CreateTime).ServerTime(DateTimeKind.Local);
    a.Property((TaskInfo b) => b.LastRunTime).ServerTime(DateTimeKind.Local);
})
//配置任务日志表
.ConfigEntity<TaskLog>(a =>
{
    a.Name("app_task_log");
    a.Property((TaskLog b) => b.Exception).StringLength(-1);
    a.Property((TaskLog b) => b.Remark).StringLength(-1);
    a.Property((TaskLog b) => b.CreateTime).ServerTime(DateTimeKind.Local);
});

添加任务常量

在 MyCompanyName.MyProjectName.Api\Core\Consts 目录添加任务常量TaskNames.cs

cs
namespace MyCompanyName.MyProjectName.Api.Core.Consts;

/// <summary>
/// 任务常量
/// </summary>
public static partial class TaskNames
{
    /// <summary>
    /// 任务名称
    /// </summary>
    public const string ModuleTaskName = "ModuleTaskName";
}

添加模块任务处理器

在 MyCompanyName.MyProjectName.Api\Core\Handlers 目录添加模块任务处理器ModuleTaskHandler.cs

cs
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Threading.Tasks;
using FreeScheduler;
using ZhonTai.Admin.Tools.TaskScheduler;
using ZhonTai.Common.Extensions;
using MyCompanyName.MyProjectName.Api.Services.Module;
using MyCompanyName.MyProjectName.Api.Core.Consts;
using TaskStatus = FreeScheduler.TaskStatus;

namespace MyCompanyName.MyProjectName.Api.Core.Handlers;

/// <summary>
/// 模块任务处理器
/// </summary>
public class ModuleTaskHandler : TaskHandler
{
    public ModuleTaskHandler(IFreeSql fsql) : base(fsql)
    {

    }

    /// <summary>
    /// 模块任务
    /// </summary>
    /// <param name="task"></param>
    private static async Task ModuleTask(TaskInfo task)
    {
        using var scope = TaskSchedulerServiceExtensions.ServiceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope();
        var moduleService = scope.ServiceProvider.GetRequiredService<IModuleService>();
        var dics = JsonConvert.DeserializeObject<Dictionary<string, string>>(task.Body);
        var moduleId = dics["moduleId"];
        var result = await moduleService.GetAsync(moduleId.ToLong());
        if (result.Success)
        {
            //完成并结束任务
            task.Status = TaskStatus.Completed;
        }
    }

    public override void OnExecuting(Scheduler scheduler, TaskInfo task)
    {
        switch (task.Topic)
        {
            //模块任务
            case TaskNames.ModuleTaskName:
                Task.Run(async () => {
                    await ModuleTask(task);
                }).Wait();
                break;
        }
    }
}

添加模块自定义任务处理器

在 MyCompanyName.MyProjectName.Api\Core\Handlers 目录添加模块自定义任务处理器AppCustomTaskHandler.cs

cs
using FreeScheduler;
using System;

namespace MyCompanyName.MyProjectName.Api.Core.Handlers;

/// <summary>
/// 模块自定义任务处理器
/// </summary>
public class AppCustomTaskHandler : ITaskIntervalCustomHandler
{
    public TimeSpan? NextDelay(TaskInfo task)
    {
        //利用 cron 功能库解析 task.IntervalArgument 得到下一次执行时间
        //与当前时间相减,得到 TimeSpan,若返回 null 则任务完成
        return TimeSpan.FromSeconds(5);
    }
}

使用任务调度

cs
namespace MyCompanyName.MyProjectName.Api.Services.Module;

/// <summary>
/// 模块服务
/// </summary>
[DynamicApi(Area = ApiConsts.AreaName)]
public class ModuleService : BaseService, IModuleService, IDynamicApi
{
    private IModuleRepository _moduleRepository => LazyGetRequiredService<IModuleRepository>();

    public ModuleService()
    {
    }

    /// <summary>
    /// 执行任务
    /// </summary>
    /// <returns></returns>
    public void ExecuteTask()
    {
        var scheduler = LazyGetRequiredService<Scheduler>();
        //方式1:添加任务组,第一组每次间隔15秒,第二组每次间隔2分钟
        scheduler.AddTask(TaskNames.ModuleTaskName, JsonConvert.SerializeObject(new
        {
            moduleId = 1
        }), new int[] { 15, 15, 120, 120 });

        //方式2:添加任务,每次间隔15秒
        scheduler.AddTask(TaskNames.ModuleTaskName, JsonConvert.SerializeObject(new
        {
            moduleId = 1
        }), 2, 15);

        //方式3:无限循环任务,每次间隔10分钟
        scheduler.AddTask(TaskNames.ModuleTaskName, JsonConvert.SerializeObject(new
        {
            moduleId = 1
        }), -1, 600);

        //方式4:每天凌晨执行一次
        scheduler.AddTaskRunOnDay(TaskNames.ModuleTaskName, JsonConvert.SerializeObject(new
        {
            moduleId = 1
        }), 1, "0:00:00");

        //方式5:每周一晚上11点半执行一次,0为周日,1-6为周一至周六
        scheduler.AddTaskRunOnWeek(TaskNames.ModuleTaskName, JsonConvert.SerializeObject(new
        {
            moduleId = 1
        }), 1, "1:23:30:00");

        //方式6:每个月1号下午4点执行1次
        scheduler.AddTaskRunOnMonth(TaskNames.ModuleTaskName, JsonConvert.SerializeObject(new
        {
            moduleId = 1
        }), 1, "1:16:00:00");

        //方式7:自定义cron表达式,从0秒开始每10秒执行一次
        scheduler.AddTaskCustom(TaskNames.ModuleTaskName, JsonConvert.SerializeObject(new
        {
            moduleId = 1
        }), "0/10 * * * * ?");
    }
}