WorkerServices中使用Quartz.Net

前言

搞一个后台程序,定时去执行一些操作(定时任务)

本来想搞一个控制台程序,直接小黑框去运行,
但是都2021年了,想搞一个同样能在Linux下运行的程序...
(不出意外的话,这个程序的一生都上不了Linux...)

后来发现了Worker Service ...

新建项目 & 添加依赖项

新建Worker Service 项目
Visual Studio 2019 --> 文件-->新建项目-->Worker Service


添加依赖项

Install-Package Quartz.Extensions.Hosting -Version 3.3.1

Nuget.Quartz.Extensions.Hosting


上代码

Program.cs


public class Program
{
	public static void Main(string[] args)
	{
		var configuration = GetConfiguration();
		CreateHostBuilder(configuration, args).Build().Run();
	}

	public static IHostBuilder CreateHostBuilder(IConfiguration configuration, string[] args) =>
		Host.CreateDefaultBuilder(args)
		.UseWindowsService()
			.ConfigureServices((hostContext, services) =>
			{
				// Add the required Quartz.NET services
				services.AddQuartz(q =>
				{
					// Use a Scoped container to create jobs. I'll touch on this later
					q.UseMicrosoftDependencyInjectionScopedJobFactory();

					var jobModel = configuration.GetSection(nameof(JobModel)).Get<JobModel>() ?? throw new ArgumentNullException(nameof(configuration));

					// Create a "key" for the job
					var jobKey = new JobKey(jobModel.FilesSaveJobKey);

					// Register the job with the DI container
					q.AddJob<TestJob>(opts => opts.WithIdentity(jobKey));

					// Create a trigger for the job
					q.AddTrigger
					(
						opts =>
						opts
						// link to the HelloWorldJob
						.ForJob(jobKey)
						// give the trigger a unique name
						.WithIdentity(jobModel.FilesSaveTriggerUniqueName)
						//执行频率
						.WithCronSchedule(jobModel.FilesSaveCronExpression)
					);
				});

				// Add the Quartz.NET hosted service
				services.AddQuartzHostedService
				(
					q => q.WaitForJobsToComplete = true
				);
			
				////问题记录,如何TestContext添加一个单例模式(这是另外一个问题,解决在Worker中注入DbContext)
				//var mySqlModel = configuration.GetSection(nameof(MySQLModel)).Get<MySQLModel>() ?? throw new ArgumentNullException(nameof(configuration));
				//services.AddSingleton<Func<TestContext>>(() =>
				//{
				//    var optionsBuilder = new DbContextOptionsBuilder<DbContext>();
				//    optionsBuilder.UseMySQL(mySqlModel.ConnectionString);
				//    //如果有其他依赖的话,可以通过provider.GetService<XX>()来获取
				//    return new TestContext(optionsBuilder.Options);
				//});
				//services.AddSingleton<FileDownload>().AddSingleton<FileInfoUtility>();
				
				//这个自带的方法直接注释即可.
				//services.AddHostedService<Worker>();
			});



	private static IConfiguration GetConfiguration()
	{
		var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
		var builder = new ConfigurationBuilder()
			.SetBasePath(Directory.GetCurrentDirectory())
					.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
			 .AddJsonFile($"appsettings.{env}.json", true, false)
			.AddEnvironmentVariables();
		return builder.Build();
	}
}

TestJob.cs作业类



[DisallowConcurrentExecution]
public class TestJob : IJob
{
	private readonly ILogger<TestJob> _logger;
	private readonly ITestService _testService;

	public TestJob
	(
		ILogger<TestJob> logger
		, ITestService testService
	)
	{
		_logger = logger;
		_testService = testService;
	}

	public Task Execute(IJobExecutionContext context)
	{
		try
		{
			_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);			
			//主角-->男1号-->要定时执行的方法
			var result = _testService.No1_Nan();			
		}
		catch (Exception ex)
		{
			_testService.AddLogBusinessOperateAsync("运行-->异常", string.Concat(ex.Message, "-->", ex.InnerException?.Message));
			_logger.LogError($"{DateTimeOffset.Now}-->{ex.Message}-->{ex.InnerException}");
		}		
		return Task.CompletedTask;
	}
}

总结

纸上得来终觉浅 Vs 纸上得来易躬行

有些问题你看了再多的资料,
但是不经历一次问题的起止(从发现问题,深入了解问题,解决问题)
真不搞不明白咋回事.

但是有些问题,
一篇好的资料,真的能帮你迅速解决问题.


对象 Vs 关联

我们可能隐约知道一个问题中,有哪些角色,
但是很少去梳理具体有哪些角色,并且关键梳理他们之间的关系,

比如这个问题中,
我本来梳理的涉及的角色[".NET Core","Quartz.Net","Worker Service"],
我要做的就是梳理清楚{Quartz.Net}和{Worker Service}之间的关系,如何关联,才能使这2者运行起来.

过了一段时间,经过我的了解,发现了一个新的角色-->{Quartz.Extensions.Hosting}(一个官方实现使用{Quartz.Net}运行后台任务)
并且官方出品,值得信赖,

所以现在涉及的角色-->[".NET Core","Quartz.Extensions.Hosting","Worker Service"]
关于{Quartz.Extensions.Hosting}和{Worker Service}之间的关系,
在一篇资料中也很好的演示了,我也少走了很多弯路,
直接复制过来,改下参数就可以用了.

并且其中一直有个误区,
{Worker Service}中自带了一个继承自{BackgroundService}的类-->{Worker},
我刚开始一直觉得必须要将{Quartz.Extensions.Hosting}和{Worker}关联起来,
一直觉得可能要在{Worker}中运行{Quartz.Extensions.Hosting}...

结果最后发现根本不需要{Worker}的参与...


真有人连最后一段话都看?

原博客写的特别好,
但是洋洋洒洒的大篇文本,
真的看不下去,
所以我最后这些文本大家可能也看不到...
我自己记录下.




摘抄文档

原文地址:https://www.cnblogs.com/love-zf/p/14638476.html