Document

.Net Core 3.1 +Topshelf+Quartz创建Windows定时任务

 

准备工作

  • 创建.net core 控制台应用程序,这里不做过多介绍
  • 添加TopShelf包:TopShelf;
  • 添加Quartz包:Quartz、Quartz.Plugins;
  • 添加依赖注入包:Microsoft.Extensions.DependencyInjection;
  • 添加读取配置文件包:Microsoft.Extensions.Configuration.Json;
  • 添加访问数据库包:Microsoft.EntityFrameworkCore;

配置Quartz

    • 创建appsettings.json文件,右键文件属性,并更改属性为始终复制 内容
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      {
      "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 类
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      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 { getset; }
       
          public ThreadPool ThreadPool { getset; }
       
          public Plugin Plugin { getset; }
       
          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 { getset; }
      }
       
      public class ThreadPool
      {
          public string Type { getset; }
       
          public string ThreadPriority { getset; }
       
          public int ThreadCount { getset; }
      }
       
      public class Plugin
      {
          public JobInitializer JobInitializer { getset; }
      }
       
      public class JobInitializer
      {
          public string Type { getset; }
          public string FileNames { getset; }
      }

        

    • 添加一个Job

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      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

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      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

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      <?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>

        

    • 添加一个类,此类用户服务启动调用

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      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

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      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;
              }
          }

        

posted @ 2021-06-08 18:23  从未被超越  阅读(197)  评论(0)    收藏  举报