基于Quartz和Topshelf创建简单的任务调度
Quartz + Topshelf创建Windows Service
源码地址:https://github.com/qyjwork/QuartzDemo
一 Quartz
Quartz是一个完全由java编写的开源的,轻量级的作业调度框架,Quartz.Net是Quartz的.Net实现,最新版本为3.0.6
官网:http://www.quartz-scheduler.net/
源码:https://github.com/quartznet/quartznet
示例:https://www.quartz-scheduler.net/documentation/quartz-3.x/quick-start.html
二 Topshelf
Topshelf是构建Windows Service的一种方式,与传统的Win Service 相比较,更新简单,轻量,易调试
官网:http://topshelf-project.com/
基于Quartz和Topshelf创建简单的任务调度
- 创建一个控制台项目
- 通过nuget安装以下Quartz依赖
Quartz , CrystalQuartz.Owin //监控页面做准备 - 安装Topshelf需要的依赖
Topshelf, Microsoft.Owin.Hosting,Microsoft.Owin,Owin等 - 新建任务类
namespace QuartzDemo
{
//实现JJob接口 3.0之后该接口方法为async模式
public class TestJob1 : IJob
{
public async Task Execute(IJobExecutionContext context)
{
await Task.Factory.StartNew(() =>
{
var data = context.JobDetail.JobDataMap;
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:MM:ss")} TestJob1");
//以下输出可以输出任务的相信信息,包括名称等
//Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd HH:MM:ss")} {Environment.NewLine}TestJob1 Name: {data.Get("name")} TestJob1 Description:{context.JobDetail.Description} {Environment.NewLine}Trigger: Name:{context.Trigger.Key.Name} Description:{context.Trigger.Description}");
});
}
}
}
- 新建QuartzWrapper类型
namespace QuartzDemo
{
public class QuartzWrapper
{
private IScheduler scheduler = null;
private IDisposable webApp = null;
private async Task InitJob()
{
//定义任务一
IJobDetail jobDetail1 = JobBuilder.Create<TestJob1>().WithIdentity("job1", "group1").UsingJobData("name", "job1").WithDescription("this is job1").Build();
ITrigger trigger1 = TriggerBuilder.Create().WithIdentity("trigger1", "group1").WithDescription("this is job1's Trigger").WithSimpleSchedule(it => it.WithIntervalInSeconds(3).RepeatForever()).Build();
//定义任务二
IJobDetail jobDetail2 = JobBuilder.Create<TestJob2>().WithIdentity("job2", "group1").Build();
ITrigger trigger2 = TriggerBuilder.Create().WithIdentity("trigger2", "group1").WithSimpleSchedule(it => it.WithIntervalInSeconds(5).RepeatForever()).Build();
//初始化调度器
scheduler = new StdSchedulerFactory().GetScheduler().GetAwaiter().GetResult();
//将任务添加到调度器
await scheduler.ScheduleJob(jobDetail1, trigger1);
await scheduler.ScheduleJob(jobDetail2, trigger2);
}
public async Task Start()
{
//初始化任务信息
await this.InitJob();
//定义监控页面
Action<IAppBuilder> startup = app => app.UseCrystalQuartz(() => { return scheduler; });
string listeningUrl = "http://127.0.0.1:9008/";
webApp = WebApp.Start(listeningUrl, startup);
Console.WriteLine("Server is started");
Console.WriteLine("URL:" + listeningUrl);
Console.WriteLine("Starting scheduler...");
await scheduler.Start();
Console.WriteLine("scheduler is Started");
}
public void Stop()
{
this.scheduler.Clear();
this.scheduler.Shutdown(false);
}
}
}
- 修改main方法如下
static void Main(string[] args)
{
HostFactory.New(x =>
{
x.StartAutomatically();
x.UseAssemblyInfoForServiceInfo();
x.Service<QuartzWrapper>(s => {
s.ConstructUsing(srv => new QuartzWrapper());
s.WhenStarted(async job => await job.Start());
s.WhenStopped(job => job.Stop());
});
x.SetServiceName("Quartz任务");
x.SetDisplayName("Quartz任务");
x.SetDescription("Quartz任务");
x.EnableServiceRecovery(sr =>
{
sr.RestartService(1);
sr.RestartService(2);
});
}).Run();
}
1 此时运行程序 即可看到任务执行情况
打开浏览器输入代码中配置的地址:http://127.0.0.1:9008/ 可看到任务执行情况,如下图,我们可以清楚地看到任务的分组,执行时间,任务执行次数等
PS:如出现"the server factory could not be located for the given input"的错误,只需要添加Microsoft.Owin.Host.HttpListener依赖即可
种一棵树最好的时间是十年前,其次是现在.