Window服务与Quartz.NET
Quartz.NET: http://quartznet.sourceforge.net/ (现为2.2版本)
Sourceforge:http://sourceforge.net/projects/quartznet/files/quartznet (项目打开貌似有点问题)
GitHub:https://github.com/quartznet/quartznet
NuGet : http://nuget.org/packages/Quartz
stackoverflow:http://stackoverflow.com/questions/tagged/quartz.net
相对JAVA版的来说,文档太少了,我找了一个入门文档(QuartzNetQuickstart),基于XML配置的,个人认为配置更灵活,例如我写好一个服务,以后需要加任务,只需要写好实现类,修改下配置就行了。可以在如下地址下载:http://jayvilalta.com/blog/downloads/
在ASP.NET中使用,主要考虑到Application_End等一些列问题,现改用window服务。
http://asdfblog.com/technology/aspnet-scheduled-tasks-with-quartznet.html
http://blog.csdn.net/a497785609/article/details/5941283
Quartz.Net的组成
Common.Logging (一定注意版本2.1.2,或者使用相应的Nuget文件来获取)
C5(一个C#和其他CLI语言的泛型集合类, Net2.0及以上才可以使用,并支持 Mono http://www.itu.dk/research/c5/)
quartz.config(有一个默认配置)
# Default Properties file for use by StdSchedulerFactory
# to create a Quartz Scheduler Instance, if a different
# properties file is not explicitly specified.
#
quartz.scheduler.instanceName = DefaultQuartzScheduler
quartz.threadPool.threadCount = 10
quartz.threadPool.threadPriority = Normal
quartz.jobStore.misfireThreshold = 60000
window服务
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 | public partial class QuatzNTService : ServiceBase { private readonly ILog logger; private IScheduler scheduler; public QuatzNTService() { InitializeComponent(); logger = LogManager.GetLogger(GetType()); ISchedulerFactory schedulerFactory = new StdSchedulerFactory(); scheduler = schedulerFactory.GetScheduler(); } protected override void OnStart( string [] args) { scheduler.Start(); logger.Info( "Quartz服务成功启动" ); } protected override void OnStop() { scheduler.Shutdown( true ); logger.Info( "Quartz服务成功终止" ); } protected override void OnPause() { scheduler.PauseAll(); } protected override void OnContinue() { scheduler.ResumeAll(); } } |
任务
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 | /// <summary> /// This is just a simple job that says "Hello" to the world. /// </summary> /// <author>Bill Kratzer</author> /// <author>Marko Lahma (.NET)</author> public class HelloJob : IJob { private static readonly ILog logger = LogManager.GetLogger( typeof (HelloJob)); /// <summary> /// Called by the <see cref="IScheduler" /> when a <see cref="ITrigger" /> /// fires that is associated with the <see cref="IJob" />. /// </summary> /// <remarks> /// The implementation may wish to set a result object on the /// JobExecutionContext before this method exits. The result itself /// is meaningless to Quartz, but may be informative to /// <see cref="IJobListener" />s or /// <see cref="ITriggerListener" />s that are watching the job's /// execution. /// </remarks> /// <param name="context">The execution context.</param> public void Execute(IJobExecutionContext context) { logger.Info( "HelloJob running..." ); Thread.Sleep(TimeSpan.FromSeconds(5)); logger.Info( "HelloJob run finished." ); } |
log4j
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 | <?xml version= "1.0" encoding= "utf-8" ?> <configuration> <configSections> <section name= "quartz" type= "System.Configuration.NameValueSectionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <section name= "log4net" type= "log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> <sectionGroup name= "common" > <section name= "logging" type= "Common.Logging.ConfigurationSectionHandler, Common.Logging" /> </sectionGroup> </configSections> <common> <logging> <factoryAdapter type= "Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter, Common.Logging.Log4net1211" > <arg key= "configType" value= "INLINE" /> </factoryAdapter> </logging> </common> <log4net> <!--控制台日志--> <appender name= "ConsoleAppender" type= "log4net.Appender.ConsoleAppender" > <layout type= "log4net.Layout.PatternLayout" > <conversionPattern value= "%d [%t] %-5p %l - %m%n" /> </layout> </appender> <!--文本信息日志--> <appender name= "InfoFileAppender" type= "log4net.Appender.RollingFileAppender" > <file value= "log/" /> <appendToFile value= "true" /> <param name= "DatePattern" value= "yyyyMMdd" .txt "" /> <rollingStyle value= "Date" /> <maxSizeRollBackups value= "100" /> <maximumFileSize value= "1024KB" /> <staticLogFileName value= "false" /> <Encoding value= "UTF-8" /> <filter type= "log4net.Filter.LevelRangeFilter" > <param name= "LevelMin" value= "INFO" /> <param name= "LevelMax" value= "INFO" /> </filter> <layout type= "log4net.Layout.PatternLayout" > <conversionPattern value= "%date %-5level %logger - %message%newline" /> </layout> </appender> <!--文本错误日志--> <appender name= "ErrorFileAppender" type= "log4net.Appender.RollingFileAppender" > <file value= "log/error.txt" /> <appendToFile value= "true" /> <rollingStyle value= "Size" /> <maxSizeRollBackups value= "100" /> <maximumFileSize value= "10240KB" /> <staticLogFileName value= "true" /> <Encoding value= "UTF-8" /> <filter type= "log4net.Filter.LevelRangeFilter" > <param name= "LevelMin" value= "WARN" /> <param name= "LevelMax" value= "FATAL" /> </filter> <layout type= "log4net.Layout.PatternLayout" > <conversionPattern value= "%date %-5level %logger - %message%newline" /> </layout> </appender> <root> <level value= "INFO" /> <appender- ref ref = "ConsoleAppender" /> <appender- ref ref = "InfoFileAppender" /> <appender- ref ref = "ErrorFileAppender" /> <!-- uncomment to enable event log appending --> <!-- <appender- ref ref = "EventLogAppender" /> --> </root> </log4net> <!-- We use quartz.config for this server, you can always use configuration section if you want to. Configuration section has precedence here. --> <!-- <quartz> <add key= "quartz.scheduler.instanceName" value= "ExampleDefaultQuartzScheduler" /> <add key= "quartz.threadPool.type" value= "Quartz.Simpl.SimpleThreadPool, Quartz" /> <add key= "quartz.threadPool.threadCount" value= "10" /> <add key= "quartz.threadPool.threadPriority" value= "2" /> <add key= "quartz.jobStore.misfireThreshold" value= "60000" /> <add key= "quartz.jobStore.type" value= "Quartz.Simpl.RAMJobStore, Quartz" /> </quartz> --> <startup> <supportedRuntime version= "v4.0" sku= ".NETFramework,Version=v4.5" /> </startup> </configuration> |
配置
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 | <?xml version= "1.0" encoding= "UTF-8" ?> <!-- This file contains job definitions in schema version 2.0 format --> <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>HelloJob</name> < group >HelloJobGroup</ group > <description>Hello job for Quartz</description> <job-type>Quartz.Example.HelloJob, Quartz.Example</job-type> <durable> true </durable> <recover> false </recover> </job> <trigger> <cron> <name>HelloTrigger</name> < group >HelloTriggerGroup</ group > <description>Simple trigger to simply fire sample job</description> <job-name>HelloJob</job-name> <job- group >HelloJobGroup</job- group > <!--每10秒中执行一次--> <cron-expression>0/10 * * * * ?</cron-expression> </cron> </trigger> <!-- <trigger> <simple> <name>HelloTrigger</name> < group >HelloTriggerGroup</ group > <description>Simple trigger to simply fire Hello job</description> <job-name>HelloJob</job-name> <job- group >HelloJobGroup</job- group > <misfire-instruction>SmartPolicy</misfire-instruction> <repeat-count>-1</repeat-count> <repeat-interval>10000</repeat-interval> </simple> </trigger> --> </schedule> </job-scheduling-data> |
安装服务 C:\Windows\Microsoft.NET\Framework64\v4.0.30319 InstallUtil C:\IIS\QuatzServiceQuatz.Service.exe
卸载服务 C:\Windows\Microsoft.NET\Framework64\v4.0.30319 InstallUtil /u C:\IIS\QuatzServiceQuatz.Service.exe
日志
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 | 2013-11-16 19:04:42,219 INFO Quartz.Impl.StdSchedulerFactory - Using default implementation for object serializer 2013-11-16 19:04:42,246 INFO Quartz.Impl.StdSchedulerFactory - Using default implementation for ThreadExecutor 2013-11-16 19:04:42,261 INFO Quartz.Core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: Quartz.Core.SchedulerSignalerImpl 2013-11-16 19:04:42,262 INFO Quartz.Core.QuartzScheduler - Quartz Scheduler v.2.2.400.0 created. 2013-11-16 19:04:42,268 INFO Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin - Registering Quartz Job Initialization Plug- in . 2013-11-16 19:04:42,270 INFO Quartz.Simpl.RAMJobStore - RAMJobStore initialized. 2013-11-16 19:04:42,284 INFO Quartz.Simpl.RemotingSchedulerExporter - Remoting is allowing remote calls 2013-11-16 19:04:42,285 INFO Quartz.Simpl.RemotingSchedulerExporter - Registering remoting channel of type 'System.Runtime.Remoting.Channels.Tcp.TcpChannel' to port (555) with name (httpQuartz) 2013-11-16 19:04:42,286 INFO Quartz.Simpl.RemotingSchedulerExporter - Remoting channel registered successfully 2013-11-16 19:04:42,287 INFO Quartz.Simpl.RemotingSchedulerExporter - Successfully marhalled remotable scheduler under name 'QuartzScheduler' 2013-11-16 19:04:42,290 INFO Quartz.Core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.2.400.0) 'ServerScheduler' with instanceId 'NON_CLUSTERED' Scheduler class : 'Quartz.Core.QuartzScheduler' - access via remote incovation. NOT STARTED. Currently in standby mode. Number of jobs executed: 0 Using thread pool 'Quartz.Simpl.SimpleThreadPool' - with 10 threads. Using job-store 'Quartz.Simpl.RAMJobStore' - which does not support persistence. and is not clustered. 2013-11-16 19:04:42,291 INFO Quartz.Impl.StdSchedulerFactory - Quartz scheduler 'ServerScheduler' initialized 2013-11-16 19:04:42,291 INFO Quartz.Impl.StdSchedulerFactory - Quartz scheduler version: 2.2.400.0 2013-11-16 19:04:42,301 INFO Quartz.Xml.XMLSchedulingDataProcessor - Parsing XML file: C:\IIS\QuatzService\quartz_jobs.xml with systemId: ~/quartz_jobs.xml 2013-11-16 19:04:42,492 INFO Quartz.Xml.XMLSchedulingDataProcessor - Adding 1 jobs, 1 triggers. 2013-11-16 19:04:42,496 INFO Quartz.Xml.XMLSchedulingDataProcessor - Adding job: HelloJobGroup.HelloJob 2013-11-16 19:04:42,534 INFO Quartz.Core.QuartzScheduler - Scheduler ServerScheduler_$_NON_CLUSTERED started. 2013-11-16 19:04:42,535 INFO Quatz.Service.QuatzNTService - Quartz服务成功启动 2013-11-16 19:04:50,019 INFO Quartz.Example.HelloJob - HelloJob running... 2013-11-16 19:04:55,021 INFO Quartz.Example.HelloJob - HelloJob run finished. 2013-11-16 19:05:00,001 INFO Quartz.Example.HelloJob - HelloJob running... 2013-11-16 19:05:05,002 INFO Quartz.Example.HelloJob - HelloJob run finished. 2013-11-16 19:05:10,000 INFO Quartz.Example.HelloJob - HelloJob running... 2013-11-16 19:05:15,000 INFO Quartz.Example.HelloJob - HelloJob run finished. 2013-11-16 19:05:19,999 INFO Quartz.Example.HelloJob - HelloJob running... 2013-11-16 19:05:25,000 INFO Quartz.Example.HelloJob - HelloJob run finished. 2013-11-16 19:05:30,000 INFO Quartz.Example.HelloJob - HelloJob running... 2013-11-16 19:05:35,000 INFO Quartz.Example.HelloJob - HelloJob run finished. 2013-11-16 19:05:40,000 INFO Quartz.Example.HelloJob - HelloJob running... 2013-11-16 19:05:45,000 INFO Quartz.Example.HelloJob - HelloJob run finished. 2013-11-16 19:05:49,999 INFO Quartz.Example.HelloJob - HelloJob running... 2013-11-16 19:05:54,999 INFO Quartz.Example.HelloJob - HelloJob run finished. 2013-11-16 19:06:00,000 INFO Quartz.Example.HelloJob - HelloJob running... 2013-11-16 19:06:05,000 INFO Quartz.Example.HelloJob - HelloJob run finished. 2013-11-16 19:06:10,004 INFO Quartz.Example.HelloJob - HelloJob running... 2013-11-16 19:06:15,005 INFO Quartz.Example.HelloJob - HelloJob run finished. 2013-11-16 19:06:20,000 INFO Quartz.Example.HelloJob - HelloJob running... 2013-11-16 19:06:25,000 INFO Quartz.Example.HelloJob - HelloJob run finish |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述