haswell架构,欧比斯疾走,金煌棋牌
{ "quartz": { "scheduler": { "instancename": "job" }, "threadpool": { "type": "quartz.simpl.simplethreadpool, quartz", "threadpriority": "normal", "threadcount": 10 }, "plugin": { "jobinitializer": { "type": "quartz.plugin.xml.xmlschedulingdataprocessorplugin, quartz.plugins", "filenames": "quartz_jobs.xml" } } } }
namespace job { public class quartzoption { public quartzoption(iconfiguration config) { if (config == null) { throw new argumentnullexception(nameof(config)); } var section = config.getsection("quartz"); section.bind(this); } public scheduler scheduler { get; set; } public threadpool threadpool { get; set; } public plugin plugin { get; set; } public namevaluecollection toproperties() { var properties = new namevaluecollection { ["quartz.scheduler.instancename"] = scheduler?.instancename, ["quartz.threadpool.type"] = threadpool?.type, ["quartz.threadpool.threadpriority"] = threadpool?.threadpriority, ["quartz.threadpool.threadcount"] = threadpool?.threadcount.tostring(), ["quartz.plugin.jobinitializer.type"] = plugin?.jobinitializer?.type, ["quartz.plugin.jobinitializer.filenames"] = plugin?.jobinitializer?.filenames }; return properties; } } public class scheduler { public string instancename { get; set; } } public class threadpool { public string type { get; set; } public string threadpriority { get; set; } public int threadcount { get; set; } } public class plugin { public jobinitializer jobinitializer { get; set; } } public class jobinitializer { public string type { get; set; } public string filenames { get; set; } } }
namespace job { public class syncjob : ijob { private readonly iservice _service; public syncjob(iservice service) { _service = service; } public async task execute(ijobexecutioncontext context) { log.information("同步开始..."); _service.dosomething(); } } }
namespace job { public class jobfactory : ijobfactory { protected readonly iserviceprovider container; public jobfactory(iserviceprovider container) { container = container; } public ijob newjob(triggerfiredbundle bundle, ischeduler scheduler) { return container.getservice(bundle.jobdetail.jobtype) as ijob; } public void returnjob(ijob job) { (job as idisposable)?.dispose(); } } }
文件名与appsetting中的quartz.plugin.jobinitializer.filenames 保持一致
<?xml version="1.0" encoding="utf-8"?> <job-scheduling-data xmlns="http://quartznet.sourceforge.net/jobschedulingdata" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" version="2.0"> <processing-directives> <overwrite-existing-data>true</overwrite-existing-data> </processing-directives> <schedule> <job> <name>syncjob</name> <group>syncgroup</group> <description>数据同步任务</description> <job-type>mille.job.syncjob, mille.job</job-type> <durable>true</durable> <recover>false</recover> </job> <trigger> <cron> <name>synctrigger</name> <group>syncgroup</group> <description>同步触发器</description> <job-name>syncdjob</job-name> <job-group>syncgroup</job-group> <!--每晚23:50跑一次,具体参见cron表达式--> <cron-expression>0 50 23 ? * *</cron-expression> </cron> </trigger> <!--<trigger> <simple> <name>synctrigger</name> <group>syncgroup</group> <description>数据同步触发器</description> <job-name>syncjob</job-name> <job-group>syncgroup</job-group> <repeat-count>-1</repeat-count> 2s跑一次 <repeat-interval>2000</repeat-interval> </simple> </trigger>--> </schedule> </job-scheduling-data>
namespace job { public class syncservice { public async task startasync() { var provider = registerservices(); scheduler = provider.getservice(typeof(ischeduler)) as ischeduler; await scheduler.start(); log.information("quartz调度已启动..."); } public async task stopasync() { await scheduler.shutdown(); log.information("quartz调度结束..."); log.closeandflush(); } #region utils private ischeduler scheduler { get; set; } private static serviceprovider registerservices() { log.information("配置依赖注入..."); var configuration = readfromappsettings(); var services = new servicecollection(); #region services.addscoped<syncservice>(); services.adddbcontext<datacontext>(opt => opt.usemysql(configuration.getconnectionstring("connstr"))); services.addscoped<iservice,service>(); #endregion #region quartz log.information("配置quartz..."); services.addscoped<ijobfactory, jobfactory>(); services.addsingleton(service => { var option = new quartzoption(configuration); var sf = new stdschedulerfactory(option.toproperties()); var scheduler = sf.getscheduler().result; scheduler.jobfactory = service.getservice<ijobfactory>(); return scheduler; }); services.addscoped<syncjob>(); //此处不能写成services.addscoped<ijob,syncjob>(); 会造成在找不到syncjob #endregion var provider = services.buildserviceprovider(); return provider; } private static iconfigurationroot readfromappsettings() { //读取appsettings.json return new configurationbuilder() .setbasepath(directory.getcurrentdirectory()) .addjsonfile("appsettings.json", false) .build(); } #endregion } }
详情参见
namespace job { public class program { public static void main(string[] args) { instancelog(); var rc = hostfactory.run(x => { x.service<syncservice>(s => { s.constructusing(name => new syncservice()); s.whenstarted(async tc => await tc.startasync()); //调用此方法前勿有太多操作,会造成服务启动失败 s.whenstopped(async tc => await tc.stopasync()); }); x.runaslocalsystem(); x.setdescription("syncjob description"); x.setdisplayname("syncjob displayname"); x.setservicename("syncjob servicename"); }); var exitcode = (int)convert.changetype(rc, rc.gettypecode()); environment.exitcode = exitcode; } private static void instancelog() { //配置serilog var template = "{timestamp:hh:mm:ss} [{level:u3}] {message}{newline}{exception}"; log.logger = new loggerconfiguration() .writeto.file(path: "logs/log.txt", outputtemplate: template, rollinginterval: rollinginterval.day) .writeto.console(logeventlevel.information) .createlogger(); } } }
<propertygroup> <outputtype>exe</outputtype> <targetframework>netcoreapp3.0</targetframework> <runtimeidentifier>win7-x64</runtimeidentifier>//不同的环境rid不同 </propertygroup>
编译项目之后,进入到/bin/debug/netcoreapp3.0/win7-x64目录,在此处以管理员运行cmd,然后执行 依次job.exe install 安装服务, job.exe start 启动服务
如果遇到启动服务时报 1053错误:服务没有及时响应启动或控制请求。检查start函数调用之前是否还有其他操作,如有,请将这些操作移动到start调用后执行;本人就是由于在start之前执行了依赖注入等操作,导致服务启动失败,故写下这篇文章
此文章有部分借鉴其他博主的博客,如有侵权,请联系删除
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
Blazor server side 自家的一些开源的, 实用型项目的进度之 CEF客户端
.NET IoC模式依赖反转(DIP)、控制反转(Ioc)、依赖注入(DI)
vue+.netcore可支持业务代码扩展的开发框架 VOL.Vue 2.0版本发布
网友评论