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
|