在我们日常开发工作中, 经常会运用到 Quartz+Topshelf 组件的组合来开发一些定时任务. 那么在. Net Core 下如何去使用呢? 我自己尝试搭建了一个测试项目, 过程中遇到了以下一些问题:
Quartz 配置文件及版本问题. 我们知道 Quartz 有 2 个配置文件, quartz.config 和 quartz.job.xml. 前者负责组件初始化配置, 后者负责 job 和 triggle 的配置. 刚开始我是直接把 framework 下的配置文件直接拿过来用的, 启动直接报错. 主要问题在 quartz.config
quartz.plugin.xml.type = Quartz.Plugin.xml.XMLSchedulingDataProcessorPlugin, Quartz
这一段上. 原因 Quartz 最新版本已经将 Plugin 模块单独剥离出一个独立的 DLL, 这里的引用也要变化. 需要 Nuget 上下载 Quartz.Plugins 组件, 并将上一段改成
quartz.plugin.xml.type = Quartz.Plugin.xml.XMLSchedulingDataProcessorPlugin, Quartz.Plugins
DI 问题. 为了贴合. Net Core DI 精神, 我们也要来实现 Console 程序的 DI 功能. 第一个问题是 Job 如何 DI? 首先我们需要自己去实现 JobFactory
- public class NewJobFactory : IJobFactory
- {
- private readonly IServiceProvider _serviceProvider;
- public NewJobFactory(IServiceProvider serviceProvider)
- {
- _serviceProvider = serviceProvider;
- }
- public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
- {
- return _serviceProvider.GetService(bundle.JobDetail.JobType) as IJob;
- }
- public void ReturnJob(IJob job)
- {
- var disposable = job as IDisposable;
- disposable?.Dispose();
- }
- }
注入方式
- IServiceCollection services = new ServiceCollection();
- services.AddScoped<IJobFactory, NewJobFactory>();
- services.AddSingleton(service =>
- {
- var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result;
- scheduler.JobFactory = service.GetService<IJobFactory>();
- return scheduler;
- });
Console 程序的配置文件获取以及注入问题. 众所周知,.Net Core 下建立的 Console 程序就是一块白板, 什么都没有. 配置文件我们还得自己去建一个. JSON 文件. 并且需要自己从 Nuget 上下载的组件包 (见后面项目结构截图). 加载方式如下
- private IConfiguration ConfigureConfiguration()
- {
- // 配置文件
- var builder = new ConfigurationBuilder()
- .SetBasePath(Directory.GetCurrentDirectory())
- .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
- return builder.Build();
- }
注入方式如下
- if (configuration != null)
- {
- //iconfiguration 注入
- services.AddSingleton<IConfiguration>(configuration);
- }
- // 自定义 option 方式注入
- services.Configure<AppSetting>(configuration);
这样就可以在后续的类代码中 直接通过 DI 方式获取 IConfiguration 对象或者你自己的 Option 对象了
贴上完整代码.
Program.cs
- static void Main(string[] args)
- {
- HostFactory.Run(x =>
- {
- x.Service<ServiceRunner>();
- x.SetDescription("gt.dotnetcore.consolesample");
- x.SetDisplayName("gt.dotnetcore.consolesample");
- x.SetServiceName("gt.dotnetcore.consolesample");
- x.StartAutomatically();
- });
- }
ServiceRunner.cs 启动的核心
- public class ServiceRunner : ServiceControl
- {
- //private readonly IScheduler _scheduler;
- private IServiceProvider _serviceProvider;
- public ServiceRunner()
- {
- var configurationRoot = ConfigureConfiguration();
- _serviceProvider = ConfigureServices(configurationRoot);
- }
- private IConfiguration ConfigureConfiguration()
- {
- // 配置文件
- var builder = new ConfigurationBuilder()
- .SetBasePath(Directory.GetCurrentDirectory())
- .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
- return builder.Build();
- }
- private IServiceProvider ConfigureServices(IConfiguration configuration)
- {
- // 依赖注入
- IServiceCollection services = new ServiceCollection();
- // 后续需要使用 log 的话, 这里需要注入
- services.AddTransient<ILoggerFactory, LoggerFactory>();
- services.AddTransient<ITest, TestBiz>();
- services.AddScoped<IJobFactory, NewJobFactory>();
- if (configuration != null)
- {
- //iconfiguration 注入
- services.AddSingleton<IConfiguration>(configuration);
- }
- // 自定义 option 方式注入
- services.Configure<AppSetting>(configuration);
- // 这里注意 Job 的注入方式, 不要强制指定 IJob 实现方式!!
- services.AddScoped<TestJob>();
- services.AddScoped<Test2Job>();
- services.AddSingleton(service =>
- {
- var scheduler = StdSchedulerFactory.GetDefaultScheduler().Result;
- scheduler.JobFactory = service.GetService<IJobFactory>();
- return scheduler;
- });
- // 构建容器
- return services.BuildServiceProvider();
- }
- public bool Start(HostControl hostControl)
- {
- var scheduler = _serviceProvider.GetService(typeof(IScheduler)) as IScheduler;
- scheduler.Start();
- return true;
- }
- public bool Stop(HostControl hostControl)
- {
- var scheduler = _serviceProvider.GetService(typeof(IScheduler)) as IScheduler;
- scheduler.Shutdown(true);
- return true;
- }
- }
Test2Job.cs
- public class Test2Job : IJob
- {
- private ITest _testService;
- private AppSetting _appsetting;
- private IConfiguration _configuration;
- public Test2Job(ITest testService, IOptionsMonitor<AppSetting> appSettingAccessor, IConfiguration configuration)
- {
- _testService = testService;
- _appsetting = appSettingAccessor.CurrentValue;
- _configuration = configuration;
- }
- public Task Execute(IJobExecutionContext context)
- {
- Console.WriteLine($"job2222222222222 started:{_appsetting.TestCN}");
- var t = _testService.Dowork(1);
- t.Wait();
- Console.WriteLine($"job2222222222222 ended:{_configuration["TestCN"]}");
- return Task.CompletedTask;
- }
- }
项目结构截图
附项目源码 https://gitee.com/gt1987/gt.dotnetcore
来源: https://www.cnblogs.com/gt1987/p/11806053.html