首页 > 其他分享 >Quartz NetCore定时器任务应用之基于Quartz

Quartz NetCore定时器任务应用之基于Quartz

时间:2023-03-04 09:47:07浏览次数:47  
标签:定时器 NetCore private IJob Quartz Task logger public

Quartz Net 是一个强大,开源,轻量的作业调度框架,可以创建简单或复杂的作业调度来执行一个Task。

Quartz主要由3部分组成:

Scheduler:调度器,根据Trigger中设置调用周期执行Job。

Trigger:触发器,设置Job执行周期。

Job:具体需要执行的业务。

本篇介绍Quartz在netcore中的一种应用纯Quartz类库开发netcore定时器任务,下篇会介绍通过Quartz.Extensions.Hosting类库更简便的开发基于netcore的定时器任务

1、Quartz,通过Manage NuGet Pakage / Pakage Manage Console 安装Quartz,当前最新版本3.6.2

 2、创建2个任务(IJob)ServiceJobA,ServiceJobB分别设置DisallowConcurrentExecution attribute,阻止并发调用

[DisallowConcurrentExecution]
public class ServiceJobA : IJob
{
    private readonly ILogger<ServiceJobA> _logger;

    public ServiceJobA(ILogger<ServiceJobA> logger)
    {
        _logger = logger;
    }   

    public Task Execute(IJobExecutionContext context)
    {
        Task.Run(() => 
        {
            _logger.LogInformation($"DateTime.Now: {DateTime.Now.ToLongTimeString()}, The service job A has been excuted.");
        });
        return Task.CompletedTask;
    }
}
ServiceJobA
using Quartz;

namespace API.Quartz.QuartzV2;

[DisallowConcurrentExecution]
public class ServiceJobB : IJob
{
    private readonly ILogger<ServiceJobA> _logger;

    public ServiceJobB(ILogger<ServiceJobA> logger)
    {
        _logger = logger;
    }

    public Task Execute(IJobExecutionContext context)
    {
        Task.Run(() =>
        {
            _logger.LogInformation($"DateTime.Now: {DateTime.Now.ToLongTimeString()}, The service job B has been excuted.");
        });
        return Task.CompletedTask;
    }
}
ServiceJobB

3、创建QuartzJobFactory,目的是通过ServiceProvider从容器中获取IJob,可以参考Quartz源码中Quartz.Simpl.SimpleJobFactory,创建自定义JobFactory之后就可以给调度器(Scheduler)指定自定义的JobFactory。

using Quartz;
using Quartz.Spi;

namespace API.Quartz.QuartzV2
{
    public class QuartzJobFactory : IJobFactory
    {
        private readonly IServiceProvider _serviceProvider;
        public QuartzJobFactory(IServiceProvider serviceProvider)
        { 
            _serviceProvider = serviceProvider;
        }

        public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            return _serviceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
        }

        /// <summary>
        /// Allows the job factory to destory/cleanup the job if needed
        /// </summary>
        /// <param name="job"></param>
        public void ReturnJob(IJob job)
        {
            var disposable = job as IDisposable;
            disposable?.Dispose();
        }
    }
}
JobFactory

通过ServcieProvider从IOC容器获取IJob,IJob的实例就需要添加到IOC容器中,从而在IJob的实例可以通过构造函数的方式实现依赖注入,比如缓存类,日志类,及第三方或自定义的service服务。

 

 4、创建HostService,轮询执行IJob

using Quartz;
using Quartz.Spi;

namespace API.Quartz.QuartzV2
{
    public class QuartzHostedService : IHostedService
    {
        private readonly ISchedulerFactory _schedulerFactory;
        private readonly IJobFactory _jobFactory;
        private readonly List<JobScheduler> _jobSchedulers;

        public QuartzHostedService(ISchedulerFactory schedulerFactory, 
            IJobFactory jobFactory,
            List<JobScheduler> jobSchedulers)
        {
            _schedulerFactory = schedulerFactory ?? throw new ArgumentNullException(nameof(schedulerFactory));
            _jobFactory = jobFactory ?? throw new ArgumentNullException(nameof(jobFactory));
            _jobSchedulers = jobSchedulers ?? throw new ArgumentNullException(nameof(jobSchedulers));
        }

        private IScheduler _scheduler { get; set; }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            _scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
            _scheduler.JobFactory = _jobFactory;
            foreach (var jobScheduler in _jobSchedulers)
            {
                var job = CreateJob(jobScheduler);
                var trigger = CreateTrigger(jobScheduler);
                await _scheduler.ScheduleJob(job, trigger, cancellationToken);
            }
            await _scheduler.Start(cancellationToken);
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            await _scheduler.Shutdown(cancellationToken);
        }

        private static IJobDetail CreateJob(JobScheduler schedule)
            => JobBuilder.Create(schedule.JobType).WithIdentity(schedule.JobType.Name).WithDescription(schedule.JobType.FullName).Build();

        private static ITrigger CreateTrigger(JobScheduler schedule)
            => TriggerBuilder.Create().WithIdentity($"{schedule.JobType.Name}.trigger").WithCronSchedule(schedule.CronString).WithDescription(schedule.CronString).Build();
    }
}
HostService

 

_scheduler = await _schedulerFactory.GetScheduler(cancellationToken);

这里之所以能用构造函数依赖注入的_schedulerFactory是因为在IOC容器中注入了StdSchedulerFactory

  builder.Services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();

  获取到调度器(Scheduler)之后,给Scheduler指定JobFactory,及以上创建的QuartzJobFactory

  _scheduler.JobFactory = _jobFactory;

5、为了调用方便,这里又定义了一个Job和Trigger的关系类JobTrigger,指定JobType及Cron表达式

namespace API.Quartz.QuartzV2;
public class JobTrigger
{
    public Type JobType { get; private set; }
    public String CronString { get; private set; }
    public JobTrigger(Type jobType, string cronString)
    {
        JobType = jobType;
        CronString = cronString;
    }
}
JobTrigger

6、在IOC容器中注入StdSchedulerFactory, ServiceJobA,ServiceJobB及初始化一系列JobTrigger任务串,最后向IOC中注入了自定义的QuartzHostedService

var config = builder.Configuration;
builder.Services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
builder.Services.AddTransient<API.Quartz.QuartzV2.ServiceJobA>();
builder.Services.AddTransient<API.Quartz.QuartzV2.ServiceJobB>();
builder.Services.AddSingleton<IJobFactory, QuartzJobFactory>();
builder.Services.AddSingleton(sp
    => new List<JobTrigger>
    {
        new JobTrigger(typeof(API.Quartz.QuartzV2.ServiceJobA), config[$"Quartz:{typeof(API.Quartz.QuartzV2.ServiceJobA).Name}"]),
        new JobTrigger(typeof(API.Quartz.QuartzV2.ServiceJobB), config[$"Quartz:{typeof(API.Quartz.QuartzV2.ServiceJobB).Name}"])
    });
builder.Services.AddHostedService<QuartzHostedService>();
IOC

7、appsettings.json 配置了每个IJob 调用的周期Cron

  "Quartz": {
    "ServiceJobA": "0/5 * * * * ?",
    "ServiceJobB": "0/30 * * * * ?"
  }

工程文件目录

 

启动程序,效果如下:

 

 JobServiceA每5s执行一次,JobServiceB每30s执行一次。

标签:定时器,NetCore,private,IJob,Quartz,Task,logger,public
From: https://www.cnblogs.com/qindy/p/17168527.html

相关文章

  • Quartz NetCore定时器任务应用之基于Quartz.Extension.Hosting
    上一篇主要介绍基于Quartz原生类库开发netcore定时器任务,有关Quartz的基本概念这里也不再累述了,接下来主要介绍基于Quartz.Extension.Hosting扩展类库快速开发。1、通过Ma......
  • NetCore Ocelot
       Ocelot是一个用.NETCore实现并且开源的API网关,功能包括:路由,请求聚合,服务验证,鉴权,限流熔断,并内置了负载均衡器与ServiceFabric,ButteflyTracing集成。这些功能都......
  • NetCore Ocelot 之 请求聚合 Aggregator
    Ocelot允许声明聚合路由,把多个Routes请求batch一个对象来对客户端的请求进行响应。1、ocelotconfiguration{"DownstreamPathTemplate":"/api/service1",......
  • NetCore 之 DispatchProxy
    如何使用Dispatchproxy封装RESTAPI,让API调用更简单。1、创建HttpClientDispathProxy类继承自DispatchProxypublicclassHttpClientDispathProxy<TInterface>:D......
  • NetCore JWT token
    在netcore中jwt使用场景很多,网上有很多的资料,这里不再累述,之后有机会会单独介绍,今天主要以实战为主。1、createjwttoken1publicinterfaceIJwtTokenService2......
  • NetCore Resource
    在netcore中resource的配置及应用1、创建resource资源文件   2、在容器中添加配置1builder.Services.AddLocalization(options=>options.ResourcesPath="......
  • docker下netcore内存dump
    一般开发阶段可以通过visualstudio来检查程序的内存、cup等的优化问题。vs下调试=》性能探查器,这里面大有千秋。但是好多内存问题是经过时间积累下来才暴露出来的,在生产......
  • winfrom quartz 实现任务信息绑定到窗体上
    一个任务可以绑定多个触发器但是一个触发器不能绑定多个任务 使用委托实现多线程同步窗体publicpartialclassForm1:Form{publicstaticForm1......
  • QuartZ
    Quartz.NET是一个强大、开源、轻量级的任务调度框架。任务调度在我们的开发中经常遇到,如说:每天晚上三点让程序或网站执行某些代码,或者每隔5秒种执行一个方法等。Windows......
  • 如何在Windows窗体中使用Quartz .net?
    好!我浪费了太多时间来解决这个问题,使Quartz.net在windows窗体上工作。但是,我有一个通用的解决方案,我希望能帮助其他人。像往常一样创建IJOB类创建一个指向表单的静态......