准备工作
- 创建.net core 控制台应用程序,这里不做过多介绍
- 添加TopShelf包:TopShelf;
- 添加Quartz包:Quartz、Quartz.Plugins;
- 添加依赖注入包:Microsoft.Extensions.DependencyInjection;
- 添加读取配置文件包:Microsoft.Extensions.Configuration.Json;
- 添加访问数据库包:Microsoft.EntityFrameworkCore;
配置Quartz
- 创建appsettings.json文件,右键文件属性,并更改属性为始终复制 内容
{ "quartz": { "scheduler": { "instanceName": "Job" }, "threadPool": { "type": "Quartz.Simpl.SimpleThreadPool, Quartz", "threadPriority": "Normal", "threadCount": 10 }, "plugin": { "jobInitializer": { "type": "Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz.Plugins", "fileNames": "quartz_jobs.xml" } } } }
- 创建QuartzOption 类
public class QuartzOption { public QuartzOption(IConfiguration config) { if (config == null) { throw new ArgumentNullException(nameof(config)); } var section = config.GetSection("quartz"); section.Bind(this); } public Scheduler Scheduler { get; set; } public ThreadPool ThreadPool { get; set; } public Plugin Plugin { get; set; } public NameValueCollection ToProperties() { var properties = new NameValueCollection { ["quartz.scheduler.instanceName"] = Scheduler?.InstanceName, ["quartz.threadPool.type"] = ThreadPool?.Type, ["quartz.threadPool.threadPriority"] = ThreadPool?.ThreadPriority, ["quartz.threadPool.threadCount"] = ThreadPool?.ThreadCount.ToString(), ["quartz.plugin.jobInitializer.type"] = Plugin?.JobInitializer?.Type, ["quartz.plugin.jobInitializer.fileNames"] = Plugin?.JobInitializer?.FileNames }; return properties; } } public class Scheduler { public string InstanceName { get; set; } } public class ThreadPool { public string Type { get; set; } public string ThreadPriority { get; set; } public int ThreadCount { get; set; } } public class Plugin { public JobInitializer JobInitializer { get; set; } } public class JobInitializer { public string Type { get; set; } public string FileNames { get; set; } }
-
添加一个Job
public class TestJob : IJob { private readonly IService _service; public SyncJob(IService service) { _service = service; } public async Task Execute(IJobExecutionContext context) { Log.Information("同步开始..."); _service.DoSomeThing(); } }
-
实现IJobFactory
public class JobFactory : IJobFactory { protected readonly IServiceProvider Container; public JobFactory(IServiceProvider container) { Container = container; } public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) { return Container.GetService(bundle.JobDetail.JobType) as IJob; } public void ReturnJob(IJob job) { (job as IDisposable)?.Dispose(); } }
-
创建Quartz调度的配置文件 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> <!--TestJob测试 任务配置--> <job> <name>TestJob</name> <group>ServerGroup</group> <description>上传视频</description> <job-type>Server.TestJob, Server</job-type> <durable>true</durable> <recover>false</recover> </job> <trigger> <cron> <name>TestJobTrigger</name> <group>ServerGroup</group> <job-name>TestJob</job-name> <job-group>ServerGroup</job-group> <cron-expression>0/60 * * * * ?</cron-expression> </cron> </trigger> <!--TestJob2测试 任务配置--> <!-- <job> <name>TestJob2</name> <group>Test</group> <description>TestJob2测试</description> <job-type>CoreSolution.Job.jobs.TestJob2,CoreSolution.Job</job-type> <durable>true</durable> <recover>false</recover> </job> <trigger> <cron> <name>TestJob2Trigger</name> <group>Test</group> <job-name>TestJob2</job-name> <job-group>Test</job-group> <cron-expression>0/30 * * * * ?</cron-expression> --> <!--30s执行一次--> <!-- </cron> </trigger>--> </schedule> </job-scheduling-data>
-
添加一个类,此类用户服务启动调用
-
public sealed class ServiceRunner : ServiceControl, ServiceSuspend { //调度器 private readonly IScheduler scheduler; public ServiceRunner() { scheduler = StdSchedulerFactory.GetDefaultScheduler().GetAwaiter().GetResult(); } //开始 public bool Start(HostControl hostControl) { scheduler.Start(); return true; } //停止 public bool Stop(HostControl hostControl) { scheduler.Shutdown(false); return true; } //恢复所有 public bool Continue(HostControl hostControl) { scheduler.ResumeAll(); return true; } //暂停所有 public bool Pause(HostControl hostControl) { scheduler.PauseAll(); return true; } }
-
配置TopShelf
class Program { static void Main(string[] args) { var rc = HostFactory.Run(x => { x.Service<ServiceRunner>(s => { s.ConstructUsing(name => new ServiceRunner()); s.WhenStarted((tc, hc) => tc.Start(hc)); s.WhenStopped((tc, hc) => tc.Stop(hc)); s.WhenContinued((tc, hc) => tc.Continue(hc)); s.WhenPaused((tc, hc) => tc.Pause(hc)); }); x.RunAsLocalService(); x.StartAutomaticallyDelayed(); x.RunAsLocalSystem(); x.SetDescription("测试后台服务"); x.SetDisplayName("TestServer"); x.SetServiceName("TestServer"); x.EnablePauseAndContinue(); }); var exitCode = (int)Convert.ChangeType(rc, rc.GetTypeCode()); Environment.ExitCode = exitCode; } }