Quartz.Net在windows服务中的使用

时间:2021-10-13 17:33:59

写在前面

这几天在弄一个项目,需要定时抓取一些数据,当时也想直接用timer算了。因为之前也弄过这样的项目,但是一想,已经用过了,再去使用同一种思路,未免太乏味了。就换了一种新玩法。这里将之前看到的一篇文章中提出的一个思路,在这个项目中实践了一下,发现乐在其中。

Quarzt.net

[转]C#创建服务及使用程序自动安装服务,.NET创建一个即是可执行程序又是Windows服务的exe

这篇文章,给了一种好玩的方式,并且自己也实践了一下,而且也确确实实在项目中用到了。

简单一个demo,先熟悉如何使用Quartz.NET

Quartz.Net在windows服务中的使用

关于如何windows service的内容,这里不再赘述,一搜一大堆。

首先引入lib中的dll。

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
using Quartz;
using Quartz.Job;
using Common.Logging;
using Quartz.Impl;
using Statistics.WindowService.JobManager;
using System.Configuration;
namespace Statistics.WindowService
{
/// <summary>
/// 数据同步windows服务
/// </summary>
public partial class SyncDataService : ServiceBase
{
private readonly ILog logger;
private IScheduler scheduler;
//时间间隔
private readonly string StrCron = ConfigurationManager.AppSettings["cron"] == null ? "* 10 * * * ?" : ConfigurationManager.AppSettings["cron"];
/// <summary>
///构造函数
/// </summary>
public SyncDataService()
{
InitializeComponent();
//初始化
logger = LogManager.GetLogger(this.GetType());
//新建一个调度器工工厂
ISchedulerFactory factory = new StdSchedulerFactory();
//使用工厂生成一个调度器
scheduler = factory.GetScheduler(); }
/// <summary>
/// 服务开启
/// </summary>
/// <param name="args"></param>
protected override void OnStart(string[] args)
{
if (!scheduler.IsStarted)
{
//启动调度器
scheduler.Start();
//新建一个任务
IJobDetail job = JobBuilder.Create<AppLogJob>().WithIdentity("AppLogJob", "AppLogJobGroup").Build();
//新建一个触发器
ITrigger trigger = TriggerBuilder.Create().StartNow().WithCronSchedule(StrCron).Build();
//将任务与触发器关联起来放到调度器中
scheduler.ScheduleJob(job, trigger);
logger.Info("Quarzt 数据同步服务开启");
} }
/// <summary>
/// 服务停止
/// </summary>
protected override void OnStop()
{
if (!scheduler.IsShutdown)
{
scheduler.Shutdown();
}
}
/// <summary>
/// 暂停
/// </summary>
protected override void OnPause()
{
scheduler.PauseAll();
base.OnPause();
}
/// <summary>
/// 继续
/// </summary>
protected override void OnContinue()
{
scheduler.ResumeAll();
base.OnContinue();
}
}
}

时间间隔采用的是cron表达式,关于cron表达式的定义,可以参考这篇文章:http://www.cnblogs.com/linjiqin/archive/2013/07/08/3178452.html

定义Job,可以通过自定义类,并且实现IJob接口,可以很方便的定义一个任务,并且也非常容易扩展。

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using Quartz;
7 using Quartz.Job;
8 namespace Statistics.WindowService.JobManager
9 {
10 /// <summary>
11 /// 同步applog任务
12 /// </summary>
13 public class AppLogJob:IJob
14 {
15 //使用Common.Logging.dll日志接口实现日志记录
16 private static readonly Common.Logging.ILog logger = Common.Logging.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
17 /// <summary>
18 /// 定时任务执行
19 /// </summary>
20 /// <param name="context"></param>
21 public void Execute(IJobExecutionContext context)
22 {
23 try
24 {
25 logger.Info("AppLogJob 任务开始运行");
26
27 for (int i = 0; i < 10; i++)
28 {
29 logger.InfoFormat("AppLogJob 正在运行{0}", i);
30 }
31
32 logger.Info("AppLogJob 任务运行结束");
33 }
34 catch (Exception ex)
35 {
36 logger.Error("AppLogJob 运行异常", ex);
37 }
38 }
39 }
40 }

修改windows 服务的入口程序:

 using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks; namespace Statistics.WindowService
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
static void Main(string[] args)
{
//如果传递了参数 s 就启动服务
if (args.Length > && args[] == "s")
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new SyncDataService() };
ServiceBase.Run(ServicesToRun);
}
else
{
Console.WriteLine("这是Windows应用程序");
Console.WriteLine("请选择,[1]安装服务 [2]卸载服务 [3]退出");
var rs = int.Parse(Console.ReadLine());
string strServiceName = "syncService[数据同步服务]";
switch (rs)
{
case :
//取当前可执行文件路径,加上"s"参数,证明是从windows服务启动该程序
var path = Process.GetCurrentProcess().MainModule.FileName + " s";
Process.Start("sc", "create " + strServiceName + " binpath= \"" + path + "\" displayName= " + strServiceName + " start= auto");
Console.WriteLine("安装成功");
Console.Read();
break;
case :
Process.Start("sc", "delete " + strServiceName + "");
Console.WriteLine("卸载成功");
Console.Read();
break;
case : break;
} } }
}
}

修改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.Log4net">
<arg key="configType" value="INLINE"/>
</factoryAdapter>
</logging>
</common>
<log4net>
<appender name="InfoFileAppender" type="log4net.Appender.RollingFileAppender">
<file value="log/" />
<appendToFile value="true" />
<param name="DatePattern" value="yyyyMMdd&quot;.txt&quot;" />
<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="InfoFileAppender" />
<appender-ref ref="ErrorFileAppender" />
</root>
</log4net>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<appSettings>
<!--每五分钟执行一次-->
<add key="cron" value="* 5 * * * ?"/>
</appSettings>
</configuration>

弄这个demo的目的是先让Quartz.net
找到bin目录下的exe文件,右键以管理员身份运行。

Quartz.Net在windows服务中的使用

查看生成的log日志

 2015-05-22 10:43:23,115 INFO  Quartz.Impl.StdSchedulerFactory  - Default Quartz.NET properties loaded from embedded resource file
2015-05-22 10:43:23,147 INFO Quartz.Impl.StdSchedulerFactory - Using default implementation for object serializer
2015-05-22 10:43:23,168 INFO Quartz.Impl.StdSchedulerFactory - Using default implementation for ThreadExecutor
2015-05-22 10:43:23,181 INFO Quartz.Core.SchedulerSignalerImpl - Initialized Scheduler Signaller of type: Quartz.Core.SchedulerSignalerImpl
2015-05-22 10:43:23,181 INFO Quartz.Core.QuartzScheduler - Quartz Scheduler v.2.0.0.400 created.
2015-05-22 10:43:23,184 INFO Quartz.Simpl.RAMJobStore - RAMJobStore initialized.
2015-05-22 10:43:23,186 INFO Quartz.Core.QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.0.0.400) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
Scheduler class: 'Quartz.Core.QuartzScheduler' - running locally.
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. 2015-05-22 10:43:23,186 INFO Quartz.Impl.StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized
2015-05-22 10:43:23,187 INFO Quartz.Impl.StdSchedulerFactory - Quartz scheduler version: 2.0.0.400
2015-05-22 10:43:23,191 INFO Quartz.Core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
2015-05-22 10:43:23,250 INFO Statistics.WindowService.SyncDataService - Quarzt 数据同步服务开启
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务开始运行
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行0
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行1
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行2
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行3
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行4
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行5
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行6
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行7
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行8
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行9
2015-05-22 10:44:01,042 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务运行结束
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务开始运行
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行0
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行1
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行2
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行3
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行4
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行5
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行6
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行7
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行8
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行9
2015-05-22 10:45:03,518 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务运行结束
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务开始运行
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行0
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行1
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行2
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行3
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行4
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行5
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行6
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行7
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行8
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行9
2015-05-22 10:46:03,557 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务运行结束
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务开始运行
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行0
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行1
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行2
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行3
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行4
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行5
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行6
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行7
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行8
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行9
2015-05-22 10:47:03,373 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务运行结束
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务开始运行
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行0
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行1
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行2
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行3
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行4
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行5
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行6
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行7
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行8
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行9
2015-05-22 10:48:03,170 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务运行结束
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务开始运行
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行0
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行1
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行2
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行3
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行4
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行5
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行6
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行7
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行8
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 正在运行9
2015-05-22 10:49:01,001 INFO Statistics.WindowService.JobManager.AppLogJob - AppLogJob 任务运行结束
2015-05-22 10:49:17,048 INFO Quartz.Core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.
2015-05-22 10:49:17,048 INFO Quartz.Core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused.
2015-05-22 10:49:17,052 INFO Quartz.Core.QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED Shutdown complete.

总结

内容很简单。只是将之前在博客园看到的一种方式在项目中实践了一下。

参考文章:

http://www.cnblogs.com/lzrabbit/archive/2012/04/15/2448326.html