创建一个控制台应用程序
控制台应用程序需要加Common.Logging.dll,Common.Logging.Core.dll,Topshelf.dll,Topshelf.Log4Net.dll
如果服务有操作数据库,则还需加EntityFramework.dll和EntityFramework.SqlServer.dll
Main方法体插入代码
static void Main(string[] args)
{
HostFactory.Run(x =>
{
//x.UseAssemblyInfoForServiceInfo();
x.Service<BackTaskService>(s =>
{
s.ConstructUsing(name => new 后台任务调度BLL());
s.WhenStarted(tc => tc.OnStart(Environment.CurrentDirectory));
s.WhenStopped(tc => tc.OnStop());
});
x.SetServiceName("服务名称");
x.SetDisplayName("服务描述");
x.SetInstanceName("项目实例名称");
x.SetDescription("详细描述");
x.RunAsLocalSystem();
x.StartAutomatically();
});
}
创建后台任务调用类
需要注意私有构造函数里面需要读取xml配置文件:quartz_jobs.xml
public class 后台任务调度BLL
{
protected static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// SchedulerFactory接口私有变量
/// </summary>
/// <remarks>
/// <para> Wu Changhong(2019/10/25)</para>
/// </remarks>
private ISchedulerFactory schedulerFactory;
/// <summary>
/// Scheduler接口私有变量
/// </summary>
/// <remarks>
/// <para> Wu Changhong(2019/10/25)</para>
/// </remarks>
private IScheduler scheduler;
/// <summary>
/// 私有构造函数
/// </summary>
/// <remarks>
/// <para> Wu Changhong(2019/10/25)</para>
/// </remarks>
public 后台任务调度BLL()
{
NameValueCollection properties = new NameValueCollection();
properties["quartz.scheduler.instanceName"] = "XmlConfiguredInstance";
properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
properties["quartz.threadPool.threadCount"] = "10";
properties["quartz.threadPool.threadPriority"] = "Normal";
// job initialization plugin handles our xml reading, without it defaults are used
properties["quartz.plugin.xml.type"] = "Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz";
properties["quartz.plugin.xml.fileNames"] = "~/quartz_jobs.xml";
schedulerFactory = new StdSchedulerFactory(properties);
//scheduler = schedulerFactory.GetScheduler();
}
public string RootPath { get; set; }
/// <summary>
/// 启动任务
/// </summary>
/// <remarks>
/// <para> Wu Changhong(2019/10/25)</para>
/// </remarks>
public void OnStart(string rootPath)
{
if (scheduler != null)
return;
try
{
RootPath = rootPath;
log.Info("站点物理路径:" + RootPath);
if (scheduler == null)
{
scheduler = schedulerFactory.GetScheduler();
}
scheduler.Start();
log.Info("后台任务启动");
}
catch (Exception e)
{
log.Error(e.Message, e);
}
}
/// <summary>
/// 停止任务
/// </summary>
/// <remarks>
/// <para> Wu Changhong(2019/10/25)</para>
/// </remarks>
public void OnStop()
{
try
{
if (scheduler != null)
scheduler.Shutdown(true);
log.Info("后台任务停止");
}
catch (Exception e)
{
log.Error(e.Message, e);
}
}
/// <summary>
/// 暂停任务
/// </summary>
/// <remarks>
/// <para> Wu Changhong(2019/10/25)</para>
/// </remarks>
public void OnPause()
{
try
{
if (scheduler != null)
scheduler.PauseAll();
}
catch (Exception e)
{
log.Error(e.Message, e);
}
}
/// <summary>
/// 继续任务
/// </summary>
/// <remarks>
/// <para> Wu Changhong(2019/10/25)</para>
/// </remarks>
public void OnContinue()
{
try
{
if (scheduler != null)
scheduler.ResumeAll();
}
catch (Exception e)
{
log.Error(e.Message, e);
}
}
}
quartz_jobs.xml配置文件内容
<?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-->
<job>
<name>任务配置类名称</name>
<group>任务配置类分组名称</group>
<description>说明</description>
<job-type>任务配置类完整引用地址.OrderPayQueryJob,任务配置类项目引用地址</job-type>
<durable>true</durable>
<recover>false</recover>
</job>
<trigger>
<cron>
<name>OrderPayQueryJobTrigger</name>
<group>任务配置类分组名称</group>
<job-name>任务配置类名称</job-name>
<job-group>任务配置类分组名称</job-group>
<start-time>2017-06-20T00:00:00+08:00</start-time>
<cron-expression>0/1 * * * * ?</cron-expression><!--请求次数控制(参见cron表达式)-->
</cron>
</trigger>
<!--任务配置类二Job-->
<job>
<name>任务配置类名称</name>
<group>任务配置类分组名称</group>
<description>说明</description>
<job-type>任务配置类完整引用地址.OrderPayQueryJob,任务配置类项目引用地址</job-type>
<durable>true</durable>
<recover>false</recover>
</job>
<trigger>
<cron>
<name>OrderPayQueryJobTrigger</name>
<group>任务配置类分组名称</group>
<job-name>任务配置类名称</job-name>
<job-group>任务配置类分组名称</job-group>
<start-time>2017-06-20T00:00:00+08:00</start-time>
<cron-expression>0/1 * * * * ?</cron-expression><!--请求次数控制(参见cron表达式)-->
</cron>
</trigger>
</schedule>
</job-scheduling-data>
任务配置类
public class OrderPayQueryJob : BaseJob
{
protected static log4net.ILog log =
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// 同步处理的变量
/// </summary>
private static readonly object sysObject = new object();
/// <summary>
/// 是否正在执行
/// </summary>
private static bool isDoing = false;
/// <summary>
/// 活动报名Job
/// </summary>
protected override void ExecuteJob()
{
try
{
lock (sysObject)
{
if (isDoing)
return;
isDoing = true;
}
try
{
Execute();
}
finally
{
isDoing = false;
}
}
catch (Exception em)
{
isDoing = false;
log.Error(em);
}
}
private void Execute()
{
//自己的业务
}
}
任务继承BaseJob 类
public abstract class BaseJob : IJob
{
protected static log4net.ILog log =
log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Job的实现
/// </summary>
/// <param name="context">Job执行的Context</param>
/// <remarks>
/// <para> 2019/10/25</para>
/// </remarks>
public void Execute(IJobExecutionContext context)
{
ExecuteJob();
}
/// <summary>
/// 调用具体的Job实现
/// </summary>
protected abstract void ExecuteJob();
}
安装和卸载服务
服务名称.exe install
服务名称.exe uninstall