先上效果图:数据是写死模拟的。
背景:公司项目需求,需要每天或每小时20分定时推送消息给用户。
技术:基于微软强大的.net平台,引用第三方[Quartz 2.5.0.0]任务调度器(后面会专门写一个Quartz的安装使用教程),使用C#高级语法委托的方式实现消息的收集和发布。下面介绍开发步骤。
1.引入Quartz 2.5.0.0插件。 如图
2.创建窗体程序。
3.编码,包含写入注册表,开机自启,初始化调度器配合作业和时间触发器加入调度器。
using Microsoft.Win32;
using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static Quartz.PushAlarmService;
namespace Quartz2
{
public partial class Form1 : Form
{
IScheduler scheduler = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
//this.DealMessage(string.Format("【消息提醒】{0}启动调度器", DateTime.Now.ToString()));//会报错
//绑定消息方法
MessageServcie.Instance.OnShowMessageDlg = new ShowMessageDlg(ShowMessageBox);
//SetAutoRun("Quartz.exe", Application.StartupPath + @"\Quartz.exe", true);//开机重启
scheduler = StdSchedulerFactory.GetDefaultScheduler();//从工厂中获取一个调度器实例化
scheduler.Start();//启动调动器
//==========例子2 (执行时 作业数据传递,时间表达式使用)===========
IJobDetail job2 = JobBuilder.Create<DumbJob>()
.WithIdentity("myJob", "group1")
.UsingJobData("jobSays", "Hello World!")
.Build();
ITrigger trigger2 = TriggerBuilder.Create()
.WithIdentity("mytrigger", "group1")
.StartNow()
.WithCronSchedule("/1 * * ? * *") //时间表达式,5秒一次
.Build();
scheduler.ScheduleJob(job2, trigger2); //把作业,触发器加入调度器。
scheduler.Shutdown(); //关闭调度器。
}
catch (Exception ex)
{
this.DealMessage(string.Format("【消息提醒】{0}调度器报错,错误信息:{1}", DateTime.Now.ToString(), ex.Message));
//throw ex;
}
}
//消息处理
private void DealMessage(string msg) {
MessageServcie.Instance.OnShowMessageDlg.Invoke(msg);
}
public void ShowMessageBox(string msg) {
if (this.InvokeRequired)
{
this.Invoke(new ShowMessageDlg(ShowMessageBox), msg);
}
else {
AddMessage(msg);
}
}
private void AddMessage(string msg) {
if (this.dgvMessage.Rows.Count>10) {
dgvMessage.Rows.RemoveAt(10);
}
dgvMessage.Rows.Insert(0, msg);
dgvMessage.Rows[0].DefaultCellStyle.ForeColor = Color.ForestGreen;
}
/// <summary>
/// 设置开机自启动
/// </summary>
/// <param name="keyName">目标名</param>
/// <param name="filePath">exe路径</param>
/// <param name="AddOrCancel">启动或取消</param>
/// <returns></returns>
private bool SetAutoRun(string keyName, string filePath, bool AddOrCancel)
{
try
{
RegistryKey Local = Registry.LocalMachine;
RegistryKey runKey = Local.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run\");
if (AddOrCancel)
{
runKey.SetValue(keyName, filePath);
Local.Close();
}
else
{
if (runKey != null)
{
runKey.DeleteValue(keyName, false);
Local.Close();
}
}
}
catch (Exception ex)
{
return false;
}
return true;
}
}
}
作业类的实现,下面的代码主要是业务逻辑代码,这里模拟的静态数据作为测试,每隔1秒不断随机产生张三xxx,并加入消息提醒推送,真实环境是通过调用微信开发平台API接口推送给用户。
using Quartz2;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Quartz
{
public class PushAlarmService
{
/// <summary>
/// 作业
/// </summary>
public class DumbJob : IJob
{
/// <summary>
/// context 可以获取当前Job的各种状态。
/// </summary>
/// <param name="context"></param>
public void Execute(IJobExecutionContext context)
{
try
{
List<string> list = new List<string>();
Random ran = new Random();
int RandKey = ran.Next(1, 999);
list.Add("张三"+ RandKey);
MessageServcie.Instance.OnShowMessageDlg.Invoke(string.Format("定时添加用户成功!分别是{0},时间:{1}", list[0],DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
}
catch (Exception ex)
{
//throw ex;
}
}
}
}
}
定义一个委托类(ShowMessageDlg),来实现消息推送的收集和发布。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Quartz2
{
public delegate void ShowMessageDlg(string msg);//消息委托
public class MessageServcie
{
private static MessageServcie _instance = null;
public static MessageServcie Instance {
get {
if (_instance==null) {
_instance = new MessageServcie();
}
return _instance;
}
}
public ShowMessageDlg OnShowMessageDlg = null;//消息代理
}
}