zoukankan      html  css  js  c++  java
  • 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}的参与...


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

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




    摘抄文档

  • 相关阅读:
    PHP filter_input_array() 函数
    pt-query-digest 用法
    [SDOI2017]苹果树
    C# json 转 xml 字符串
    C# json 转 xml 字符串
    C# double 好用的扩展
    C# double 好用的扩展
    win10 uwp 使用 Microsoft.Graph 发送邮件
    win10 uwp 使用 Microsoft.Graph 发送邮件
    Sublime Text 安装中文、英文字体
  • 原文地址:https://www.cnblogs.com/love-zf/p/14638476.html
Copyright © 2011-2022 走看看