Window服务与Quartz.NET

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 /uC:\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

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值