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 ...
随机推荐
- Nginx 配置项优化详解
(1)nginx运行工作进程个数,一般设置cpu的核心或者核心数x2 如果不了解cpu的核数,可以top命令之后按1看出来,也可以查看/proc/cpuinfo文件 grep ^processor / ...
- 又写了两个实用的微信小程序
忙里偷闲,最近又写了两个小程序. 一个是手机壁纸小程序,名字叫[来搜图],特点是界面干净清爽,没有多余的东西.开发这个是因为讨厌市面上那些壁纸app那样那么多的广告,真的太影响体验了.而且小程序更加轻 ...
- jetbrains全系列可用2018
转自 https://blog.csdn.net/u014044812/article/details/78727496 仅记录前两种方法 1.授权服务器激活 优点:方便快捷 缺点:激活的人数多了就容 ...
- go 学习笔记之解读什么是defer延迟函数
Go 语言中有个 defer 关键字,常用于实现延迟函数来保证关键代码的最终执行,常言道: "未雨绸缪方可有备无患". 延迟函数就是这么一种机制,无论程序是正常返回还是异常报错,只 ...
- Roadmap of FE
未完待补充......
- 上传漏洞之常见MIME类型
常见的MIME类型 超文本标记语言文本 .html,.html text/html 普通文本 .txt text/plain RTF文本 .rtf application/rtf GIF图形 .gif ...
- SpringMVC4拦截器配置遇到的坑
目的:对get请求添加token验证(若为post请求可通过RequestBodyAdvice实现). 情景:因为有api版本管理的需求,重写了WebMvcConfigurationSupport类的 ...
- C#版ASP.NET Web API使用示例
为更好更快速的上手Webapi设计模式的接口开发,本文详细解释了在Web API接口的开发过程中,我们可能会碰到各种各样的问题总结了这篇,希望对大家有所帮助. 1:在接口定义中确定MVC的get或者P ...
- 【Python秘籍】十进制整数与二进制数的转换
最近在用Python写遗传算法时,发现需要将十进制的整数转换成二进制数,那么怎么来转换呢?当然如果你学过进制转换的有关计算方法,你可以手动编写一些函数来实现,不过总体来说还是比较麻烦的,这里介绍Pyt ...
- Django RESRframework奇淫技巧
Django RESRframework Mixins, ViewSet和router配合使用 Mixins的类共有五种 CreateModelMixin ListModelMixin Retriev ...