我是靠谱客的博主 包容冬日,最近开发中收集的这篇文章主要介绍Quartz.Net+Microsoft.Extensions.Hosting创建服务,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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代码

static 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 配置服务

/// <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

{
"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配置文件

<!-- 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代码


/// <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.Net+Microsoft.Extensions.Hosting创建服务所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部