Topshelf+Quartz在.Net Core框架下的实现
在我们日常开发工作中,经常会运用到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
Topshelf+Quartz在.Net Core框架下的实现的更多相关文章
- 分别在.NET Framework 与 .NET Core 框架下 编写Windows Service(windows服务程序)
前言,为什么会分别在两个框架下编写Windows Service,是因为最近在做区块链这块,使用的是NEO(小蚁区块链)的相关技术,NEO使用的是.net core 2.1,业务上需要写两个程序,一个 ...
- .net core+topshelf+quartz创建windows定时任务服务
.net core+topshelf+quartz创建windows定时任务服务 准备工作 创建.net core 控制台应用程序,这里不做过多介绍 添加TopShelf包:TopShelf: 添加Q ...
- 微服务框架下的思维变化-OSS.Core基础思路
如今框架两字已经烂大街了,xx公司架构设计随处可见,不过大多看个热闹,这些框架如何来的,细节又是如何思考的,相互之间的隔离依据又是什么...相信很多朋友应该依然存在自己的疑惑,特别是越来越火热的微服务 ...
- Windows Forms和WPF在Net Core 3.0框架下并不会支持跨平台
Windows Forms和WPF在Net Core 3.0框架下并不会支持跨平台 微软将WinForms和WPF带到.NET Core 3.0这一事实,相信大家都有所了解,这是否意味着它在Linux ...
- C# 6 与 .NET Core 1.0 高级编程 - 40 ASP.NET Core(下)
译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 40 章 ASP.NET Core(下)),不对的地方欢迎指出与交流. 章节出自<Professiona ...
- 一个Mini的ASP.NET Core框架的实现
一.ASP.NET Core Mini 在2019年1月的微软技术(苏州)俱乐部成立大会上,蒋金楠老师(大内老A)分享了一个名为“ASP.NET Core框架揭秘”的课程,他用不到200行的代码实现了 ...
- 200行代码,7个对象——让你了解ASP.NET Core框架的本质
2019年1月19日,微软技术(苏州)俱乐部成立,我受邀在成立大会上作了一个名为<ASP.NET Core框架揭秘>的分享.在此次分享中,我按照ASP.NET Core自身的运行原理和设计 ...
- Spring Security框架下Restful Token的验证方案
项目使用Restful的规范,权限内容的访问,考虑使用Token验证的权限解决方案. 验证方案(简要概括): 首先,用户需要登陆,成功登陆后返回一个Token串: 然后用户访问有权限的内容时需要上传T ...
- Spring 框架下 (增 删 改 )基本操作
//applicationContext.xml 配置文件 <?xml version="1.0" encoding="UTF-8"?><be ...
随机推荐
- Flask基础(03)-->创建第一个Flask程序
# 导入Flask from flask import Flask # 创建Flask的应用程序 # 参数__name__指的是Flask所对应的模块,其决定静态文件从哪个地方开始寻找 app = F ...
- 005-做题:使用 Python 生成 200 个激活码
题目:使用 Python 生成 200 个不重复的激活码 编写思路# 激活码一般是由26个大写字母和10个数字任意组合而成# 长度为12位或者16位的居多激活码# 一个激活码里的字符是可以重复的,而且 ...
- mybatis - 通用mapper
title: 玩转spring-boot-mybatis date: 2019-03-11 19:36:57 type: "mybatis" categories: mybatis ...
- Zeppelin 学习笔记之 Zeppelin安装和elasticsearch整合
Zeppelin安装: Apache Zeppelin提供了web版的类似ipython的notebook,用于做数据分析和可视化.背后可以接入不同的数据处理引擎,包括spark, hive, taj ...
- 本次作业统一标题:C语言I博客作业02
这个作业属于哪个课程 C语言程序设计1 这作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-2/homework/8655 我在这个课程的目标是 ...
- 初探内核之《Linux内核设计与实现》笔记上
内核简介 本篇简单介绍内核相关的基本概念. 主要内容: 单内核和微内核 内核版本号 1. 单内核和微内核 原理 优势 劣势 单内核 整个内核都在一个大内核地址空间上运行. 1. 简单.2. 高效 ...
- Qt5教程: (8) 标准对话框和文件对话框
1. about对话框 包含头文件 #include <QMessageBox> 添加菜单项 QAction *p3 = pDialog->addAction("关于&qu ...
- pycharm2018.2汉化 解决设置打不开问题
首先检查下是不是装了中文汉化包resources_cn.jar 如果有的话,解决办法:1.更换一个汉化包或者将原来的resources_en.jar也放进lib目录下 2.将汉化包都删除,只留下原版的 ...
- Neo4j:图数据库GraphDB(一)入门和基本查询语句
图数据库的代表:Neo4j 官网: http://neo4j.com/ 引言:为什么使用图数据库 在很多新型项目中,应用图数据库已经是势在必行的趋势了,因为图数据库可以很好的表示各种节点与关系的概念 ...
- [BZOJ1694/1742/3074]The Cow Run 三倍经验
Description John养了一只叫Joseph的奶牛.一次她去放牛,来到一个非常长的一片地,上面有N块地方长了茂盛的草.我们可 以认为草地是一个数轴上的一些点.Joseph看到这些草非常兴奋, ...