1.首先准备Nuget包:
Microsoft.Extensions.Hosting.WindowsServices
Microsoft.Extensions.Logging.Log4Net.AspNetCore
Quartz.Extensions.Hosting
Quartz.Plugins
Microsoft.Extensions.Http.Polly 如果需要用HttpClient
2.上代码
2.1 main代码
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35static async Task Main() { var baseDir = AppDomain.CurrentDomain.BaseDirectory; #region 注册DI注入 var host = Host.CreateDefaultBuilder() .ConfigureHostConfiguration(configurationBuilder => { //This is to do some basic host configuration and should only add 2 sources configurationBuilder.SetBasePath(baseDir); configurationBuilder.AddEnvironmentVariables(prefix: "ASPNETCORE_"); #if DEBUG Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Development"); #endif }) .ConfigureAppConfiguration((_context, _builder) => { var env = _context.HostingEnvironment; _builder.AddJsonFile("appsettings.json", false, true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", true, true); }) .ConfigureServices((context, _services) => { ConfigureServices(context.Configuration, _services); }) .ConfigureLogging(logging => { logging.ClearProviders(); 通过config文件实现 //logging.SetMinimumLevel(LogLevel.Information); logging.AddLog4Net(); }) .UseWindowsService() .Build(); await host.RunAsync();//启动主机 }
2.2 配置服务
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116/// <summary> /// 配置服务 /// </summary> /// <param name="configuration"></param> /// <param name="services"></param> private static void ConfigureServices(IConfiguration config, IServiceCollection services) { configuration = config; //var loglevel = configration.GetValue<string>("Logging:LogLevel:System.Net.Http.HttpClient"); //监控平台Api services.AddSingleton<IMonitorLogApiService, MonitorLogApiService>(); ///自定义HttpMessageHandler services.AddScoped<LogErrorHttpMsgHandler>(); //<IMonitorLogApiService, MonitorLogApiService> 拿到的httplient 是新的实例 services.AddHttpClient("MonitorLogApi", client => { var _WXKFBaseUrl = config.GetValue<string>("MonitorLogApi:MonitorLogApiBaseUrl"); var WXKFBaseUrl = _WXKFBaseUrl ?? "https://status-test.gileadchina.cn/api/services/MonitorLog/"; client.BaseAddress = new Uri(WXKFBaseUrl); //默认接收 client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.Timeout = TimeSpan.FromSeconds(100);//100秒超时 }) .ConfigurePrimaryHttpMessageHandler(_ => { HttpClientHandler handler = new HttpClientHandler(); handler.AllowAutoRedirect = true; return handler; }) .SetHandlerLifetime(TimeSpan.FromHours(12)) .AddHttpMessageHandler<LogErrorHttpMsgHandler>(); #region Quartz.Net // base configuration from appsettings.json services.Configure<QuartzOptions>(configuration.GetSection("Quartz")); services.AddQuartz(qz => { // as of 3.3.2 this also injects scoped services (like EF DbContext) without problems qz.UseMicrosoftDependencyInjectionJobFactory(); // or for scoped service support like EF Core DbContext // q.UseMicrosoftDependencyInjectionScopedJobFactory(); // these are the defaults qz.UseSimpleTypeLoader(); qz.UseInMemoryStore(); qz.UseDefaultThreadPool(tp => { tp.MaxConcurrency = 10; }); //使用配置文件 //qz.UseXmlSchedulingConfiguration(x => x.Files = new string[] { // "quartz_jobs.xml" //}); #region 手动添加Job // qz.ScheduleJob<HospitalTopList2BusinessJob>(trigger => // { // string time = System.Configuration.ConfigurationManager.AppSettings["AutoSendHospitalTopList2BusinessJobTriggerTime"].ToString(); //#if DEBUG // time = "0 */1 * * * ?";//每分钟执行一次 //#endif // trigger // .WithIdentity("发送进销存Dail报表,每time执行一次", "AutoSendHospitalTopList2BusinessJobGroup") // .WithCronSchedule(time) // .StartNow(); // }, jobdtl => // { // jobdtl.WithIdentity("AutoSendHospitalTopList2BusinessJob", "AutoSendHospitalTopList2BusinessJobGroup"); // }); // qz.ScheduleJob<AutoSendSalesDailyReportJob>(trigger => // { // string time = System.Configuration.ConfigurationManager.AppSettings["AutoSendSalesDailyReportJobTriggerTime"].ToString(); //#if DEBUG // time = "0 */1 * * * ?";//每分钟执行一次 //#endif // trigger // .WithIdentity("发送进销存Dail报表,每time执行一次", "AutoSendSalesDailyReportJobGroup") // .WithCronSchedule(time) // .StartNow(); // }, jobdtl => // { // jobdtl.WithIdentity("AutoSendSalesDailyReportJob", "AutoSendSalesDailyReportJobGroup"); // }); #endregion }); services.AddQuartzHostedService(qz => { // when shutting down we want jobs to complete gracefully qz.WaitForJobsToComplete = true; }); services.AddScoped<AutoSendSalesDailyReportJobTask>(); //services.AddHostedService<BackgroundJobService>(); #endregion }
2.3 appsettings.json
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27{ "Logging": { "LogLevel": { "Default": "Information", //Trace = 0, Debug = 1, Information = 2, Warning = 3, Error = 4, Critical = 5, and None = 6. "Microsoft.AspNetCore": "Warning", "System.Net.Http.HttpClient.*": "Warning" //httpclient日志等级 //"System.Net.Http.HttpClient.MonitorLogApi.LogicalHandler": "Warning", //"System.Net.Http.HttpClient.MonitorLogApi.ClientHandler": "Warning" } }, "MonitorLogApi": { //监控平台 "MonitorLogApiBaseUrl": "https://aaa.cn/api/services/MonitorLog/" }, "Quartz": { "schedName": "Report2Mail", "quartz.scheduler.instanceId": "Report2MailScheduler", "quartz.scheduler.instanceName": "Quartz Hosting Report Scheduler", "quartz.threadPool.type": "Quartz Hosting Report Scheduler", "quartz.threadPool.threadCount": 5, "quartz.threadPool.threadPriority": "Normal", "quartz.jobStore.type": "Quartz.Simpl.RAMJobStore, Quartz", "quartz.jobStore.misfireThreshold": 6000, "quartz.plugin.jobInitializer.type": "Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz.Plugins", "quartz.plugin.jobInitializer.fileNames": "quartz_jobs.xml", "quartz.plugin.jobInitializer.failOnFileNotFound": true } }
2.4 job配置文件
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58<!-- This file contains job definitions in schema version 2.0 format --> <job-scheduling-data version="2.0" xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <processing-directives> <overwrite-existing-data>true</overwrite-existing-data> </processing-directives> <schedule> <job> <!--作业名称,同一个 group 中作业名称不能相同--> <name>List2BusinessJob</name> <!--作业分组名称,表示该作业所属分组--> <group>jGP_List2BusinessJob</group> <!--描述--> <description>定时发送 </description> <!--指定作业将调用的作业实现类,格式为:命名空间.类名,程序集名称--> <job-type>MailJob.Jobs.List2BusinessJob, CODIReportJob</job-type> <!--任务完成后是否依然保存到数据库,默认为false--> <durable>true</durable> <!--应用或服务重启之后是否忽略过期任务,默认为false--> <recover>false</recover> <!--传递给IJobExecutionContext 上下文数据--> <job-data-map> <entry> <key>taskName</key> <value>List2Business</value> </entry> <entry> <key>taskNameCN</key> <value>定时发送 医院属性</value> </entry> </job-data-map> </job> <trigger> <!--复杂触发器,使用 cron-expression 设置触发器的行为 cron生成器:https://cron.qqe2.com/ --> <cron> <!--触发器名称,同一个 group 中作业名称不能相同--> <name>Tr_List2BusinessJob</name> <!--触发器分组名称,表示该触发器所属分组--> <group>GP_List2BusinessJob</group> <!--作业名,触发哪个作业,必须与 job 节点中的 group 相同--> <job-name>List2BusinessJob</job-name> <!--要调度的作业分组名称,必须与 job 节点中的 group 相同--> <job-group>jGP_List2BusinessJob</job-group> <!--开始作业的 utc 时间,北京时间需要+08:00,例如:<start-time>2017-12-01T08:00:00+08:00</start-time>,表示北京时间2017年12月1日上午8:00开始执行。 注意:服务启动或重启时都会检测此属性。若没有设置此属性,服务会根据 cron-expression 的规则执行作业调度; 若 start-time 的时间小于当前时间,服务启动后会忽略 cron-expression 的设置,立即执行一次调度,之后再根据 cron-expression 执行作业调度; 若大于当前时间,服务会等到当前时间等于 start-time 的时间才开始执行,并根据 cron-expression 执行作业调度。 如果没有特殊要求,可以忽略该属性。--> <!--<start-time>2021-12-01T00:00:00+08:00</start-time>--> <!--错过了触发 必须在 cron-expression 节点前 DoNothing:不触发立即执行。等待下次Cron触发频率到达时刻开始按照Cron频率依次执行。即如果错过了某次执行,直接忽略。 FireOnceNow:以当前时间为触发频率立刻触发一次执行,然后按照Cron频率依次执行。--> <misfire-instruction>SmartPolicy</misfire-instruction> <!--每1分钟执行一次--> <cron-expression>0 */1 * * * ?</cron-expression> </cron> </trigger> </schedule> </job-scheduling-data>
2.5 Job代码
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41/// <summary> /// 定时发送 /// PersistJobDataAfterExecution: 执行完Job后保存 JobDataMap 当中固定数据,以便任务在重复执行的时候具有相同的 JobDataMap /// DisallowConcurrentExecution:不能同时运行同一作业的多个实例 /// </summary> [PersistJobDataAfterExecution, DisallowConcurrentExecution] public class List2BusinessJob : IJob { ILogger<List2BusinessJob> _logger; AutoSendSalesDailyReportJobTask _AutoSendJobTask; public List2BusinessJob(ILogger<List2BusinessJob> logger, AutoSendSalesDailyReportJobTask AutoSendJobTask) { _logger = logger; _AutoSendJobTask = AutoSendJobTask; } public async Task Execute(IJobExecutionContext context) { AutoSendSalesDailyReportJobTask.setLogger(_logger); context.JobDetail.JobDataMap.TryGetValue("taskName", out object _taskName); context.JobDetail.JobDataMap.TryGetValue("taskNameCN", out object _taskNameCN); ThreadContext.Properties["taskName"] = _taskName ?? "List2Business"; LogicalThreadContext.Properties["taskName"] = _taskName ?? "List2Business"; ThreadContext.Properties["taskNameCN"] = _taskNameCN ?? "定时发送Job"; LogicalThreadContext.Properties["taskNameCN"] = _taskNameCN ?? "定时发送Job"; try { _logger.LogInformation($"Start Execute:Job开始执行"); //具体执行逻辑方法 await _AutoSendJobTask.BeginTaskAsync("List"); } catch (Exception ex) { _logger.LogError("Execute List2BusinessJob error:", ex.Message); } finally { _logger.LogInformation($"End Execute:Job执行结束"); } } }
最后 通过 sc create reportjob binPath="exePath" 就可以创建服务了。
Microsoft.Extensions.Hosting 可以绑定 asp.net core 程序可以是framework 4.6.1 以后的任意应用程序,快速 创建 集 configuration、dependency injection、logging 的应用,自动管理应用 生命周期。
最后
以上就是包容冬日最近收集整理的关于Quartz.Net+Microsoft.Extensions.Hosting创建服务的全部内容,更多相关Quartz内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复