震惊!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文件里面进行调用编写,编写内容主要如下:
- 创建一个作业调度池;
- 创建出来一个具体的作业;
- 创建并配置一个触发器;
- 加入作业调度池中;
- 开始运行。
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();