2020年6月4日星期四

震惊!Windows Service服务和定时任务框架quartz之间原来是这种关系……

震惊!Windows Service服务和定时任务框架quartz之间原来是这种关系……


过场CG: 接到公司领导的文件指示,“小熊”需要在6月底去海外执行一个行动代号为【定时任务】的营救计划,这个计划关系到公司某个项目的生死(数据安全漏洞),作战部拟定两个作战方案:  方案一:使用务定时任务框架quartz;  方案二:使用windows Service服务。 最终的作战方案为:两者配套使用。

 前言:项目开发完成后,对接的项目有很多个模块,由于其中的一个环节疏忽,现在需要在原有的基础上把缺失的数据自动写入数据库存储起来。重新修改程序逻辑已然不现实,现在需要一个补丁来进行逻辑更正。补丁逻辑:两个入口控制,
  • 入口一:点击【更新】按钮同步逻辑后的数据;
  • 入口二:每天晚上18:00进行执行同步逻辑后的数据;

 现在我们先使用window服务进行入口二的编写(入口一只需要一个按钮调用入口二的逻辑即可)windows服务

一、开发环境

操作系统:Windows 7 X64/32

开发环境:VS2017

编程语言:C#

.NET版本:.NET Framework 4.6.1

二、创建Windows Service

1、新建一个Windows Service,并将项目名称改为“MyWindowsService”,如下图所示:

 

 2、在解决方案资源管理器内将Service1.cs改为MyWindowsService.cs后并在左边页面空白处点击鼠标右键,添加安装程序,如下图所示:

 

添加安装程序:

 

 

3、 此时软件会生成两个组件,分别为“serviceInstaller1”及“serviceProcessInstaller1”,点击“serviceInstaller1”,右键--->属性,

将ServiceName改为MyWindowsService,Description改为“我的服务”,如下图:

 

 

 4、点击“serviceProcessInstaller1”,在“属性”窗体将Account改为LocalSystem(服务属性系统级别),如下图所示:

   5、点击MyWindowsService.cs,在左边空白位置右键,“查看代码”,然后编写代码,代码我编写好了,直接拷贝即可使用 
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;using System.Threading.Tasks;namespace MyWindowsService{ public partial class MyWindowsService : ServiceBase {  public MyWindowsService()  {   InitializeComponent();  }  //创建进程  public static Thread threadStartConfirmActualTime; //创建一个时间进程  public static Thread threadDoCheck;     //检查日志时间进程  //开启服务  protected override void OnStart(string[] args)  {   Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\t服务启动!\n");   StartServer();  }  //停止服务  protected override void OnStop()  {   Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\t服务停止!\n");  }  //启动服务操作  private void StartServer()  {   try   {    threadStartConfirmActualTime = new Thread(new ThreadStart(new SingleClass().BeginConfirmMessageTime));//在进程下面创建线程    threadStartConfirmActualTime.Start();    threadDoCheck.Start();   }   catch (Exception ex)   {    threadStartConfirmActualTime.Abort();//关闭线程    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\t服务停止!"+ex.Message+"\n");   }  }  /// <summary>  /// Aouth:xiongze  /// Time:2020/06/02  /// Details:单例模式_建立一个单例类,保证只有一个对象被实例化,然后开启服务  /// </summary>  public class SingleClass //单例模式_建立一个单例类,保证只有一个对象被实例化  {   public static SingleClass _SingleClass;   public static object onlock = new object(); //实例化一个锁   public static SingleClass Singleton   {    get    {     if (_SingleClass == null)     {      lock (onlock)      {       _SingleClass = new SingleClass();      }     }     return _SingleClass;    }   }   public void BeginConfirmMessageTime() //开启服务   {    while (true)    {     //每天晚上18这一个小时内检测执行     if (DateTime.Now.Hour.ToString("18") == "18")     {      try      {       //同步数据       Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "我在"+ DateTime.Now + "同步了数据哦!\n");      }      catch (Exception ex)      {       //记录错误日志(记录到相应的文件下面)       Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\t我是错误日志!" + ex.Message + "\n");      }     }     Thread.Sleep(1800000); //半个小时执行一次,注意,1000毫秒=1秒,具体需要多少时间可以自由换算 1800000半小时    }   }  } }}
 6、至此,Windows服务已经创建完毕。  三、创建安装、启动、停止、卸载服务的Windows窗体 1、点击项目,右键,重新生成在桌面上创建一个文件夹,命名为“我的服务”,将MyWindowsService项目项目生成的bin文件夹Debug文件夹的内容全部复制到新建的文件夹里面;然后去百度拷贝三个文件到“我的服务”文件里面,分别为Install.bat(安装)、UnInstall.bat(卸载)、InstallUtil.exe(执行),打开文件,分别打开Install.bat和UnInstall.bat文件,将后面一个xxx.exe修改为你的文件程序,我们的是MyWindowsService.exe。如下图

 

 

 

 

操作完后双击Install.bat进行安装windows服务,安装成功后点击【计算机】-->右键-->管理-->服务里面找到“我的服务”,启动服务并修改为自动启动;如下图: 

 

 

 

 

 这样就实现了windows服务入口二每天晚上18:00进行执行同步逻辑后的数据,只要代码不报错就一直执行; 优点:每天指定时间自动执行指定逻辑缺点:程序在每次设置的时间内无限执行,消耗资源(CPU等)  
 quartz定时任务
 

一、开发环境

操作系统:Windows 7 X64

开发环境:VS2017

编程语言:C#

.NET版本:.NET Framework 4.6.1

二、创建quartz定时任务1、创建一个控制台任务程序进行演示,命名为MyQuartz,创建如下: 

 

 2、引入quartz框架动态链接库

在NuGet管理里面搜索quartz进行安装,注意:Quartz高版本的存在兼容性,建议使用低版本的(2.5.0)如下图: 

 

 

3、创建一个执行的类,用于执行后台数据逻辑,命名为TestJob,并且继承Quartz框架的IJob接口,这个累的内容如下,可以直接拷贝
using Quartz;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MyQuartz{ public class TestJob: IJob {  public void Execute(IJobExecutionContext context)//指定调用的方法  {   try   {    //在这里写代码(写自己的业务逻辑)    Console.WriteLine("任务执行啦" + DateTime.Now);   }   catch (Exception ex)   {    Console.WriteLine("定时任务出错" + ex.Message);   }  } }}

4、在Program.cs文件里面进行调用编写,编写内容主要如下:

  1. 创建一个作业调度池;
  2. 创建出来一个具体的作业;
  3. 创建并配置一个触发器;
  4. 加入作业调度池中;
  5. 开始运行。
 首先我们看完成代码,然后进行讲解(代码可以直接拷贝):
using Quartz;using Quartz.Impl;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace MyQuartz{ class Program {  static void Main(string[] args)  {   //1.首先创建一个作业调度池   ISchedulerFactory schedf = new StdSchedulerFactory();   IScheduler sched = schedf.GetScheduler();   //2.创建出来一个具体的作业   IJobDetail job = JobBuilder.Create<TestJob>().Build();   //3.创建并配置一个触发器   #region(使用SimpleTrigger触发器,每次3秒执行一次,无上限)   ISimpleTrigger trigger = (ISimpleTrigger)TriggerBuilder.Create().WithSimpleSchedule(x => x.WithIntervalInSeconds(3).WithRepeatCount(int.MaxValue)).Build();