在实际的项目中,常遇到延时触发工作以及定时触发工作

这里所讲的是借助第三方的组件 Quartz.Net 来实现(源码位置:https://github.com/quartznet/quartznet)

实现思路(来自博友wuzh)

一:继承并实现IJob接口,在Execute 方法中写你要定时执行的事情(切记 )

二:使用Quartz创建任务调度核心代码步骤

  1、配置Quartz,创建工厂,开启调度。

  2、创建工作任务

  3、创建触发器

  4、将任务加入到任务池

Demo 创建控制台应用程序,定时发送邮件以及延时写日志

1 在vs2015中使用Nuget,获取Quartz

2 创建两个作业

    /// <summary>
/// 继承并实现IJob接口,在Execute 方法中写你要定时执行的事情(切记 )
/// </summary>
public class MyJob : IJob
{
public Task Execute(IJobExecutionContext context)
{
Task task = null;
try
{
string fileName = "printlog.txt";
using (StreamWriter writer = new StreamWriter(fileName, true))
{
task = writer.WriteLineAsync(string.Format("{0},测试", DateTime.Now.ToLongTimeString()));
Console.WriteLine(string.Format("{0},测试", DateTime.Now.ToLongTimeString()));
}
}
catch (Exception)
{ }
return Task.CompletedTask;
}
} /// <summary>
/// 发邮件
/// </summary>
public class SendEmailJob : IJob
{
public Task Execute(IJobExecutionContext context)
{
//Smtp
sendEmail.SendMailUseGmail("49564753X@qq.com", "49564753X@qq.com", "terryK", "Quartz.net定时作业", "Quartz.net定时发送邮件", "tiyklkinqanxbgXX", , "smtp.qq.com", true);
return Task.CompletedTask;
}
} public class sendEmail
{
public static Task SendMailUseGmail(string toUserAddress, string fromUserAddress, string fromUserName, string contextName, string context, string fromUserPass, int port, string host, bool sslState)
{
using (MailMessage mailMessage = new MailMessage())
{
mailMessage.To.Add(toUserAddress);
mailMessage.From = new MailAddress(fromUserAddress, fromUserName, Encoding.UTF8);
mailMessage.Subject = contextName;
mailMessage.SubjectEncoding = Encoding.UTF8;
mailMessage.Body = context;
mailMessage.BodyEncoding = Encoding.UTF8;
mailMessage.IsBodyHtml = false;
mailMessage.Priority = MailPriority.High;
SmtpClient smtpClient = new SmtpClient();
smtpClient.Credentials = new NetworkCredential(fromUserAddress, fromUserPass);
smtpClient.Port = port;
smtpClient.Host = host;
smtpClient.EnableSsl = sslState;
try
{
smtpClient.Send(mailMessage);
Console.WriteLine("发送成功,请查看");
}
catch (SmtpException var_3_A8)
{
Console.WriteLine(var_3_A8.ToString());
}
}
return Task.CompletedTask;
}
}

3 创建QuartzHelper,用于配置环境以及完成 IScheduler, IJobDetails 与 ITrigger之间的配置

 public class QuartzHelper
{
static readonly IScheduler _scheduler;
static QuartzHelper()
{
#region 配置 Quartz
NameValueCollection properties = new NameValueCollection
{
{"quartz.serializer.type","binary"}
};
// 设置线程池
properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
//设置线程池的最大线程数量
properties["quartz.threadPool.threadCount"] = "";
//设置作业中每个线程的优先级
properties["quartz.threadPool.threadPriority"] = ThreadPriority.Normal.ToString(); // 远程输出配置
properties["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz";
properties["quartz.scheduler.exporter.port"] = ""; //配置端口号
properties["quartz.scheduler.exporter.bindName"] = "QuartzScheduler";
properties["quartz.scheduler.exporter.channelType"] = "tcp"; //协议类型
#endregion //创建一个工厂
var schedulerFactory = new StdSchedulerFactory(properties);
//启动
_scheduler = schedulerFactory.GetScheduler().Result;
//1、开启调度
_scheduler.Start();
} /// <summary>
/// 时间间隔执行任务
/// </summary>
/// <typeparam name="T">任务类,必须实现IJob接口</typeparam>
/// <param name="seconds">时间间隔(单位:秒)</param>
public static async Task AsyncExecuteInterval<T>(int seconds) where T : IJob
{
//2、创建工作任务
IJobDetail job = JobBuilder.Create<T>()
.WithIdentity("printlog", "LogGroup")
.Build(); // 3、创建触发器
ITrigger trigger = TriggerBuilder.Create()
.StartNow()
.WithIdentity("LogTrigger", "LogGroup")
.WithSimpleSchedule(x => x.WithIntervalInSeconds(seconds).RepeatForever())
.Build(); //4、将任务加入到任务池
await _scheduler.ScheduleJob(job, trigger);
} /// <summary>
/// 指定时间执行任务
/// </summary>
/// <typeparam name="T">任务类,必须实现IJob接口</typeparam>
/// <param name="cronExpression">cron表达式,即指定时间点的表达式</param>
public static async Task<bool> AsyncExecuteByCron<T>(string cronExpression) where T : IJob
{
//2、创建工作任务
IJobDetail job = JobBuilder.Create<T>()
.WithIdentity("SendEmailJob", "EmailGroup")
.Build();
//3、创建触发器
ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
.StartNow()
.WithIdentity("SendEmail", "EmailGroup")
.WithCronSchedule(cronExpression)
.Build();
//4、将任务加入到任务池
await _scheduler.ScheduleJob(job, trigger);
return true;
}
}

4 运行调用

 public class Program
{
static void Main(string[] args)
{
Task.Run(() =>
{
string cronExpression = "0 36 15,20 ? * MON-FRI"; // =>周一到周五 每天上午8:30以及下午8:30执行定时任务(发送邮件)
QuartzHelper.AsyncExecuteByCron<SendEmailJob>(cronExpression).Wait();
});//=>这是调用Cron计划方法 Task.Run(() => QuartzHelper.AsyncExecuteInterval<MyJob>().Wait()); /*
简单说一下Cron表达式: 由7段构成:秒 分 时 日 月 星期 年(可选) "-" :表示范围 MON-WED表示星期一到星期三
"," :表示列举 MON,WEB表示星期一和星期三
"*" :表是“每”,每月,每天,每周,每年等
"/" :表示增量:0/15(处于分钟段里面) 每15分钟,在0分以后开始,3/20 每20分钟,从3分钟以后开始
"?" :只能出现在日,星期段里面,表示不指定具体的值
"L" :只能出现在日,星期段里面,是Last的缩写,一个月的最后一天,一个星期的最后一天(星期六)
"W" :表示工作日,距离给定值最近的工作日
"#" :表示一个月的第几个星期几,例如:"6#3"表示每个月的第三个星期五(1=SUN...6=FRI,7=SAT) 如果Minutes的数值是 '0/15' ,表示从0开始每15分钟执行
如果Minutes的数值是 '3/20' ,表示从3开始每20分钟执行,也就是‘3/23/43’
*/
Console.ReadKey();
}
}

5  整个Demo代码

using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace Quartz
{
public class Program
{
static void Main(string[] args)
{
Task.Run(() =>
{
string cronExpression = "0 30 8,20 ? * MON-FRI"; // =>周一到周五 每天上午8:30以及下午8:30执行定时任务(发送邮件)
QuartzHelper.AsyncExecuteByCron<SendEmailJob>(cronExpression).Wait();
});//=>这是调用Cron计划方法 Task.Run(() => QuartzHelper.AsyncExecuteInterval<MyJob>().Wait()); /*
简单说一下Cron表达式: 由7段构成:秒 分 时 日 月 星期 年(可选) "-" :表示范围 MON-WED表示星期一到星期三
"," :表示列举 MON,WEB表示星期一和星期三
"*" :表是“每”,每月,每天,每周,每年等
"/" :表示增量:0/15(处于分钟段里面) 每15分钟,在0分以后开始,3/20 每20分钟,从3分钟以后开始
"?" :只能出现在日,星期段里面,表示不指定具体的值
"L" :只能出现在日,星期段里面,是Last的缩写,一个月的最后一天,一个星期的最后一天(星期六)
"W" :表示工作日,距离给定值最近的工作日
"#" :表示一个月的第几个星期几,例如:"6#3"表示每个月的第三个星期五(1=SUN...6=FRI,7=SAT) 如果Minutes的数值是 '0/15' ,表示从0开始每15分钟执行
如果Minutes的数值是 '3/20' ,表示从3开始每20分钟执行,也就是‘3/23/43’
*/
Console.ReadKey();
}
} /// <summary>
/// 继承并实现IJob接口,在Execute 方法中写你要定时执行的事情(切记 )
/// </summary>
public class MyJob : IJob
{
public Task Execute(IJobExecutionContext context)
{
Task task = null;
try
{
string fileName = "printlog.txt";
using (StreamWriter writer = new StreamWriter(fileName, true))
{
task = writer.WriteLineAsync(string.Format("{0},测试", DateTime.Now.ToLongTimeString()));
Console.WriteLine(string.Format("{0},测试", DateTime.Now.ToLongTimeString()));
}
}
catch (Exception)
{ }
return Task.CompletedTask;
}
} /// <summary>
/// 发邮件
/// </summary>
public class SendEmailJob : IJob
{
public Task Execute(IJobExecutionContext context)
{
//Smtp
sendEmail.SendMailUseGmail("49564753X@qq.com", "49564753X@qq.com", "terryK", "Quartz.net定时作业", "Quartz.net定时发送邮件", "tiyklkinqanxbgXX", , "smtp.qq.com", true);
return Task.CompletedTask;
}
} public class sendEmail
{
public static Task SendMailUseGmail(string toUserAddress, string fromUserAddress, string fromUserName, string contextName, string context, string fromUserPass, int port, string host, bool sslState)
{
using (MailMessage mailMessage = new MailMessage())
{
mailMessage.To.Add(toUserAddress);
mailMessage.From = new MailAddress(fromUserAddress, fromUserName, Encoding.UTF8);
mailMessage.Subject = contextName;
mailMessage.SubjectEncoding = Encoding.UTF8;
mailMessage.Body = context;
mailMessage.BodyEncoding = Encoding.UTF8;
mailMessage.IsBodyHtml = false;
mailMessage.Priority = MailPriority.High;
SmtpClient smtpClient = new SmtpClient();
smtpClient.Credentials = new NetworkCredential(fromUserAddress, fromUserPass);
smtpClient.Port = port;
smtpClient.Host = host;
smtpClient.EnableSsl = sslState;
try
{
smtpClient.Send(mailMessage);
Console.WriteLine("发送成功,请查看");
}
catch (SmtpException var_3_A8)
{
Console.WriteLine(var_3_A8.ToString());
}
}
return Task.CompletedTask;
}
} public class QuartzHelper
{
static readonly IScheduler _scheduler;
static QuartzHelper()
{
#region 配置 Quartz
NameValueCollection properties = new NameValueCollection
{
{"quartz.serializer.type","binary"}
};
// 设置线程池
properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
//设置线程池的最大线程数量
properties["quartz.threadPool.threadCount"] = "";
//设置作业中每个线程的优先级
properties["quartz.threadPool.threadPriority"] = ThreadPriority.Normal.ToString(); // 远程输出配置
properties["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz";
properties["quartz.scheduler.exporter.port"] = ""; //配置端口号
properties["quartz.scheduler.exporter.bindName"] = "QuartzScheduler";
properties["quartz.scheduler.exporter.channelType"] = "tcp"; //协议类型
#endregion //创建一个工厂
var schedulerFactory = new StdSchedulerFactory(properties);
//启动
_scheduler = schedulerFactory.GetScheduler().Result;
//1、开启调度
_scheduler.Start();
} /// <summary>
/// 时间间隔执行任务
/// </summary>
/// <typeparam name="T">任务类,必须实现IJob接口</typeparam>
/// <param name="seconds">时间间隔(单位:秒)</param>
public static async Task AsyncExecuteInterval<T>(int seconds) where T : IJob
{
//2、创建工作任务
IJobDetail job = JobBuilder.Create<T>()
.WithIdentity("printlog", "LogGroup")
.Build(); // 3、创建触发器
ITrigger trigger = TriggerBuilder.Create()
.StartNow()
.WithIdentity("LogTrigger", "LogGroup")
.WithSimpleSchedule(x => x.WithIntervalInSeconds(seconds).RepeatForever())
.Build(); //4、将任务加入到任务池
await _scheduler.ScheduleJob(job, trigger);
} /// <summary>
/// 指定时间执行任务
/// </summary>
/// <typeparam name="T">任务类,必须实现IJob接口</typeparam>
/// <param name="cronExpression">cron表达式,即指定时间点的表达式</param>
public static async Task<bool> AsyncExecuteByCron<T>(string cronExpression) where T : IJob
{
//2、创建工作任务
IJobDetail job = JobBuilder.Create<T>()
.WithIdentity("SendEmailJob", "EmailGroup")
.Build();
//3、创建触发器
ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
.StartNow()
.WithIdentity("SendEmail", "EmailGroup")
.WithCronSchedule(cronExpression)
.Build();
//4、将任务加入到任务池
await _scheduler.ScheduleJob(job, trigger);
return true;
}
}
}

三分钟掌握,使用Quqrtz.Net实现定时发送邮件的更多相关文章

  1. x01.TextProc: 两三分钟完成的一个小工具

    在工作中,遇到这么个问题,需要将 Excel 表中类似 2134-1234-4456 的商品编号输入到单位的程序中,而程序只认 213412344456 这种没有 ‘-’ 的输入.数量比较多,一笔一笔 ...

  2. unity3d 三分钟实现简单的赛车漂移

    提到赛车游戏,大家最关心的应该就是漂移吧?! 从学unity开始,我就一直在断断续续的研究赛车 因为自己技术太烂.悟性太差等原因,我走了不少弯路 也许你会说,网上那么多资料,你不会查啊 是啊!网上一搜 ...

  3. 三分钟部署Laxcus大数据管理系统

    Laxcus是Laxcus大数据实验室历时五年,全体系自主设计研发的国内首套大数据管理系统.能够支撑百万台级计算机节点,提供EB量级存储和计算能力,兼容SQL和关系数据库.最新的2.x版本已经实现对当 ...

  4. JUnit三分钟教程 ---- 实际应用

    JUnit三分钟教程 ---- 实际应用 摘自http://lavasoft.blog.51cto.com/62575/65775   接上文"JUnit三分钟教程 ---- 快速起步&qu ...

  5. JUnit三分钟教程 ---- 快速起步

    JUnit三分钟教程 ---- 快速起步 摘自http://lavasoft.blog.51cto.com/62575/65625/ JUnit是个好东西,做大点的项目离不开这东西,实际中用的时候也因 ...

  6. 三分钟浅谈TT猫的前端优化

    首先看一张访问TT猫首页的截图: 测试环境为谷歌浏览器,暂且不讨论其它浏览器,截图下方我们可以观察到以下参数: DOMContentLoaded:1.42s | Load:2.31s 以上参数是在CT ...

  7. 演进之美,越来越美:三分钟看尽 iOS 1 ~ iOS 8 的进化史

    演进之美,越来越美:三分钟看尽 iOS 1 ~ iOS 8 的进化史 原文出处: 少数派 9 月 18 日苹果就将推出 iOS 8 正式版了,从 2007 年发布第一代 iPhone 时搭载在 iPh ...

  8. windows+mysql集群搭建-三分钟搞定集群

    注:本文来源:  陈晓婵   <  windows+mysql集群搭建-三分钟搞定集群   > 一:mysql集群搭建教程-基础篇 计算机一级考试系统要用集群,目标是把集群搭建起来,保证一 ...

  9. Powershell极速教程-如何在三分钟内编写项目编译脚本

    分析及思路 来看一下项目目录结构 炒鸡正常的三板斧src+docs+tests.咦,怎么会多出一个build的文件夹呢,这就是我们今天要研究的目录.今天我会带着大家在五分钟之内编写一个极简的编译脚本. ...

随机推荐

  1. Java数据类型(1)

    基本数据类型 A.整型 byte:(8位--1个字节 有符号 以二进制补码表示) 范围:-27~27-1 即 -128~127 short:(16位--2个字节 有符号 以二进制补码表示) 范围:-2 ...

  2. DF1协议简述

    DF1协议 1.    概述 可编程控制器(PLC)因编程方便,抗干扰能力强,被广泛应用于各种领域.DF1协议是AB公司可编程控制器系统广泛支持的数据链路层通信协议,各系列可编程控制器及装有RSLin ...

  3. Nginx 核心配置-长连接配置

    Nginx 核心配置-长连接配置 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.长连接配置参数说明 keepalive_timeout number; 设定保持连接超时时长,0 ...

  4. 201871010105-曹玉中《面向对象程序设计(java)》第四周学习总结

    201871010105-曹玉中<面向对象程序设计(java)>第四周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这 ...

  5. input 关键字提示,对于一些特定优化来说,很有用处

    只用html就可以做出提醒操作:效果如下图 这里是代码,怎么样,很简单吧 <form action="/server" method="post"> ...

  6. [PHP] windows下tee指令

    在win下使用tee指令 tee为Linux指令,tee把日志输出到log的同时输出到屏幕. 在 http://sourceforge.net/projects/unxutils/?source=dl ...

  7. [RN] React Native 使用 阿里 ant-design

    React Native 使用 阿里 ant-design 实例效果如图: 一.安装 npm install antd-mobile-rn --save npm install babel-plugi ...

  8. shell 命令行

    转:Davygeek 1. -eq           //等于 -ne           //不等于 -gt            //大于 (greater ) -lt            / ...

  9. c04--数组

    0.展示PTA总分 1.本章学习内容总结 1.1学习内容总结 数组查找: 1.遍历法查找:从头遍历数组找对应数据. 2.二分法查找:适用于按顺序排列的整形数组. 插入数据: 先找到该数据,对数组进行移 ...

  10. js 测试题

    //身份证号码为15位或者18位,15位时全为数字,18位前17位为数字,最后一位是校验位,可能为数字或字母x function isCardNo(card) { }$)|(^\d{}(\d|X|x) ...