一.安装nuget包
Install-Package Quartz
Install-Package Common.Logging.Log4Net1211
Install-Package log4net
Install-Package
Topshelf
二.添加IQuartzServer接口类
/// <summary>
/// Service interface for core Quartz.NET server.
/// </summary>
public interface IQuartzServer
{
/// <summary>
/// Initializes the instance of <see cref="IQuartzServer"/>.
/// Initialization will only be called once in server's lifetime.
/// </summary>
void Initialize();
/// <summary>
/// Starts this instance.
/// </summary>
void Start();
/// <summary>
/// Stops this instance.
/// </summary>
void Stop();
/// <summary>
/// Pauses all activity in scheduler.
/// </summary>
void Pause();
/// <summary>
/// Resumes all activity in server.
/// </summary>
void Resume();
}
三.添加QuartzServer类实现接口
public class QuartzServer : ServiceControl, IQuartzServer
{
private readonly ILog logger;
private ISchedulerFactory schedulerFactory;
private IScheduler scheduler;
/// <summary>
/// Initializes a new instance of the <see cref="QuartzServer"/> class.
/// </summary>
public QuartzServer()
{
logger = LogManager.GetLogger(GetType());
}
/// <summary>
/// Initializes the instance of the <see cref="QuartzServer"/> class.
/// </summary>
public virtual void Initialize()
{
try
{
schedulerFactory = CreateSchedulerFactory();
scheduler = GetScheduler();
}
catch (Exception e)
{
logger.Error("Server initialization failed:" + e.Message, e);
throw;
}
}
/// <summary>
/// Gets the scheduler with which this server should operate with.
/// </summary>
/// <returns></returns>
protected virtual IScheduler GetScheduler()
{
return schedulerFactory.GetScheduler();
}
/// <summary>
/// Returns the current scheduler instance (usually created in <see cref="Initialize" />
/// using the <see cref="GetScheduler" /> method).
/// </summary>
protected virtual IScheduler Scheduler
{
get { return scheduler; }
}
/// <summary>
/// Creates the scheduler factory that will be the factory
/// for all schedulers on this instance.
/// </summary>
/// <returns></returns>
protected virtual ISchedulerFactory CreateSchedulerFactory()
{
return new StdSchedulerFactory();
}
/// <summary>
/// Starts this instance, delegates to scheduler.
/// </summary>
public virtual void Start()
{
try
{
scheduler.Start();
}
catch (Exception ex)
{
logger.Fatal(string.Format("Scheduler start failed: {0}", ex.Message), ex);
throw;
}
logger.Info("Scheduler started successfully");
}
/// <summary>
/// Stops this instance, delegates to scheduler.
/// </summary>
public virtual void Stop()
{
try
{
scheduler.Shutdown(true);
}
catch (Exception ex)
{
logger.Error(string.Format("Scheduler stop failed: {0}", ex.Message), ex);
throw;
}
logger.Info("Scheduler shutdown complete");
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public virtual void Dispose()
{
// no-op for now
}
/// <summary>
/// Pauses all activity in scheduler.
/// </summary>
public virtual void Pause()
{
scheduler.PauseAll();
}
/// <summary>
/// Resumes all activity in server.
/// </summary>
public void Resume()
{
scheduler.ResumeAll();
}
/// <summary>
/// TopShelf's method delegated to <see cref="Start()"/>.
/// </summary>
public bool Start(HostControl hostControl)
{
Start();
return true;
}
/// <summary>
/// TopShelf's method delegated to <see cref="Stop()"/>.
/// </summary>
public bool Stop(HostControl hostControl)
{
Stop();
return true;
}
/// <summary>
/// TopShelf's method delegated to <see cref="Pause()"/>.
/// </summary>
public bool Pause(HostControl hostControl)
{
Pause();
return true;
}
/// <summary>
/// TopShelf's method delegated to <see cref="Resume()"/>.
/// </summary>
public bool Continue(HostControl hostControl)
{
Resume();
return true;
}
}
四.添加服务工厂QuartzServerFactory
public class QuartzServerFactory
{
private static readonly ILog logger = LogManager.GetLogger(typeof(QuartzServerFactory));
/// <summary>
/// Creates a new instance of an Quartz.NET server core.
/// </summary>
/// <returns></returns>
public static QuartzServer CreateServer()
{
string typeName = "QuartzTest.QuartzServer";
Type t = Type.GetType(typeName, true);
logger.Debug("Creating new instance of server type '" + typeName + "'");
QuartzServer retValue = (QuartzServer)Activator.CreateInstance(t);
logger.Debug("Instance successfully created");
return retValue;
}
}
五.添加Job类
/// <summary>
/// A sample job that just prints info on console for demostration purposes.
/// </summary>
public class SampleJob : IJob
{
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
//private static readonly ILog logger = LogManager.GetLogger(typeof(SampleJob));
/// <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("SampleJob running...");
Thread.Sleep(TimeSpan.FromSeconds(5));
logger.Info("SampleJob run finished.");
}
}
六.添加quartz.config配置文件
# You can configure your scheduler in either <quartz> configuration section
# or in quartz properties file
# Configuration section has precedence
quartz.scheduler.instanceName = ServerScheduler
# configure thread pool info
quartz.threadPool.type = Quartz.Simpl.SimpleThreadPool, Quartz
quartz.threadPool.threadCount = 10
quartz.threadPool.threadPriority = Normal
# job initialization plugin handles our xml reading, without it defaults are used
quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz
quartz.plugin.xml.fileNames = ~/quartz_jobs.xml
# export this server to remoting context
quartz.scheduler.exporter.type = Quartz.Simpl.RemotingSchedulerExporter, Quartz
quartz.scheduler.exporter.port = 555
quartz.scheduler.exporter.bindName = QuartzScheduler
quartz.scheduler.exporter.channelType = tcp
quartz.scheduler.exporter.channelName = httpQuartz
七.添加quartz_jobs.xml配置job
<?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>sampleJob</name>
<group>sampleGroup</group>
<description>Sample job for Quartz Server</description>
<job-type>QuartzTest.SampleJob, QuartzTest</job-type>
<durable>true</durable>
<recover>false</recover>
</job>
<trigger>
<simple>
<name>sampleSimpleTrigger</name>
<group>sampleSimpleGroup</group>
<description>Simple trigger to simply fire sample job</description>
<job-name>sampleJob</job-name>
<job-group>sampleGroup</job-group>
<misfire-instruction>SmartPolicy</misfire-instruction>
<repeat-count>-1</repeat-count>
<repeat-interval>10000</repeat-interval>
</simple>
</trigger>
</schedule>
</job-scheduling-data>
八.app.config文件修改
<?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.Log4net1213">
<arg key="configType" value="INLINE" />
</factoryAdapter>
</logging>
</common>
<log4net>
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
<!--日志文件名开头-->
<file value="D:\Log\Quartz\log_"/>
<!--多线程时采用最小锁定-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
<!--日期的格式,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置-->
<datePattern value="yyyyMMdd_HH".log""/>
<!--是否追加到文件,默认为true,通常无需设置-->
<appendToFile value="true"/>
<!--按照何种方式产生多个日志文件(日期[Date],文件大小[Size],混合[Composite])-->
<RollingStyle value="Composite"/>
<!--每天记录的日志文件个数,与maximumFileSize配合使用-->
<MaxSizeRollBackups value="100"/>
<!--每个日志文件的最大大小-->
<!--可用的单位:KB|MB|GB-->
<!--不要使用小数,否则会一直写入当前日志-->
<maximumFileSize value="2MB"/>
<!--是否只写到一个文件中-->
<staticLogFileName value="false" />
<!--日志格式-->
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%t]%-5p %c - %m%n"/>
</layout>
</appender>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d [%t] %-5p %l - %m%n" />
</layout>
</appender>
<appender name="EventLogAppender" type="log4net.Appender.EventLogAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d [%t] %-5p %l - %m%n" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="ConsoleAppender" />
<appender-ref ref="RollingFileAppender" />
<!--控制级别,由低到高: ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF-->
<!-- uncomment to enable event log appending -->
<!-- <appender-ref ref="EventLogAppender" /> -->
</root>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
九.主程序代码
static void Main(string[] args)
{
log4net.Config.XmlConfigurator.Configure();
// change from service account's dir to more logical one
Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);
ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
logger.Info("日志开始");
HostFactory.Run(x =>
{
x.RunAsLocalSystem();
x.SetDescription("QuartzDemo服务描述");
x.SetDisplayName("QuartzDemo服务显示名称");
x.SetServiceName("QuartzDemo服务名称");
x.Service(factory =>
{
QuartzServer server = QuartzServerFactory.CreateServer();
server.Initialize();
return server;
});
});
}
十.运行
每10秒运行一次job
参考资料:
官方学习文档:http://www.quartz-scheduler.net/documentation/index.html
使用实例介绍:http://www.quartz-scheduler.net/documentation/quartz-2.x/quick-start.html
官方的源代码下载:http://sourceforge.net/projects/quartznet/files/quartznet/