ASP .Net Core整合定时任务框架Quartz

简介

Quartz是一款优秀的定时任务框架,为应用程序中进行作业调度提供了简单却强大的机制。允许程序开发人员根据时间的间隔来调度作业。实现了作业和触发器的多对多的关系,还能把多个作业与不同的触发器关联。Quartz最初是使用Java开发的,现在也提供了.Net Core的版本。

Quartz.Net的官方网站文档:

 Quartz官方文档(英文) 

安装

在.Net Core中安装Quartz非常简单,首先打开Visual Studio,选中项目右键选择管理Nuget程序包,搜索Quartz并点击安装即可(Ps:国内下载安装可能需要科学上网)

使用方法

Quartz的使用非常简单,参照官方文档,我们首先需要到Startup.cs里面增加Quartz启动项,然后自己定义一个Job(任务)里面实现自己要执行的逻辑,最后配置Job的启动时间,下次程序到达指定事件就会自动执行你的任务了。

  • 配置StartUp启动项

打开项目,搜索startup.cs,修改ConfigureServices函数里里面的内容,可以参照下面的代码进行修改,

public IServiceProvider ConfigureServices(IServiceCollection services)
        {


            // base configuration from appsettings.json
            services.Configure<QuartzOptions>(Configuration.GetSection("Quartz"));

            // if you are using persistent job store, you might want to alter some options
            services.Configure<QuartzOptions>(options =>
            {
                options.Scheduling.IgnoreDuplicates = true; // default: false
                options.Scheduling.OverWriteExistingData = true; // default: true
            });

            services.AddQuartz(q =>
    {
        // handy when part of cluster or you want to otherwise identify multiple schedulers
        q.SchedulerId = "Scheduler-Core";

        // we take this from appsettings.json, just show it's possible
        // q.SchedulerName = "Quartz ASP.NET Core Sample Scheduler";

        // as of 3.3.2 this also injects scoped services (like EF DbContext) without problems
        q.UseMicrosoftDependencyInjectionJobFactory();

        // or for scoped service support like EF Core DbContext
        // q.UseMicrosoftDependencyInjectionScopedJobFactory();

        // these are the defaults
        q.UseSimpleTypeLoader();
        q.UseInMemoryStore();
        q.UseTimeZoneConverter();

        q.UseDefaultThreadPool(tp =>
        {
            tp.MaxConcurrency = 10;
        });

        q.ScheduleJob<HelloJob>(trigger => trigger
    .WithIdentity("Combined Configuration Trigger")
    .StartNow()
    .WithDailyTimeIntervalSchedule(x => x.WithInterval(30, IntervalUnit.Second))
    .WithDescription("my awesome trigger configured for a job with single call")
);
        

            // Quartz.Extensions.Hosting allows you to fire background service that handles scheduler lifecycle
    services.AddQuartzHostedService(options =>
    {
        // when shutting down we want jobs to complete gracefully
        options.WaitForJobsToComplete = true;
    });
  • 定义自己的job

创建一个类文件,继承IJob接口,实现Execute方法,当定时任务执行的时候,Execute方法会自动执行。参考代码如下:


    public class HelloJob : IJob
    {

        public virtual async Task Execute(IJobExecutionContext context)
        {
            //在这里面实现你的逻辑
        }
    }
  • 绑定自己的job,定义触发时间

在第一步的q.ScheduleJob已经定义了触发时间和绑定的job

        q.ScheduleJob<HelloJob>(trigger => trigger
    .WithIdentity("Combined Configuration Trigger")
    .StartNow()
    .WithDailyTimeIntervalSchedule(x => x.WithInterval(30, IntervalUnit.Second))
    .WithDescription("my awesome trigger configured for a job with single call")

WithDailyTimeIntervalSchedule函数定义了触发周期,里面是以Lambda函数的形式来定义,如果想使用crontab来定义触发时间请使用.WithCronSchedule进行替换

            .WithCronSchedule("0/3 * * * * ?")
  • 附加说明

到这里一般的定时任务都可以实现了,但是如果你想要在定时任务里面操作数据库,你需要将Service注入到Job里面,在Quartz 3.0之前还不能这样做,只能使用JobFactory做一系列操作才能实现非常复杂,Quartz 3.0以后,可以直接使用构造函数的方式进行注入了。


 public class HelloJob : IJob
    {
        private readonly IService _Service;

        public HelloJob(IService Service)
        {
            _IService = Service;
        }

        public virtual async Task Execute(IJobExecutionContext context)
        {
           //你要实现的逻辑
        }
    }
}

如果你使用的是ASP .Net Core APB框架开发,因为APB框架使用CurrentUnitWork来控制数据库的事务处理,所以上述语句在操作数据库时会报错 找不到UnitWork,你需要加几个注解和一条语句来控制事务处理

 [UnitOfWork]
 public class HelloJob : IJob
    {
        private readonly IService _Service;
        private readonly IUnitOfWorkManager _unitOfWorkManager;

        public HelloJob(IService Service,, IUnitOfWorkManager unitOfWorkManager)
        {
            _IService = Service;
            _unitOfWorkManager = unitOfWorkManager;
        }

        public virtual async Task Execute(IJobExecutionContext context)
        {
        //你需要实现的非数据库逻辑
            using (var unitOfWork = _unitOfWorkManager.Begin())
            {
               //你要实现的数据库逻辑
               unitOfWork.Complete();
             }
        }
    }
}


{{allCount}} 评论
{{item.nickName}}{{item.email}}{{item.webSiteUrl}}
{{item.createTime}}回复

{{item.content}}

{{item2.nickName}}{{item2.createTime}}

@{{item.nickName}} {{item2.content}}