使用Quqrtz.Net實現定時發送郵件,註意郵箱要開通Smtp服務 ...
在實際的項目中,常遇到延時觸發工作以及定時觸發工作
這裡所講的是藉助第三方的組件 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("[email protected]", "[email protected]", "terryK", "Quartz.net定時作業", "Quartz.net定時發送郵件", "tiyklkinqanxbgXX", 587, "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"] = "10"; //設置作業中每個線程的優先順序 properties["quartz.threadPool.threadPriority"] = ThreadPriority.Normal.ToString(); // 遠程輸出配置 properties["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz"; properties["quartz.scheduler.exporter.port"] = "555"; //配置埠號 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>(5).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>(5).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("[email protected]", "[email protected]", "terryK", "Quartz.net定時作業", "Quartz.net定時發送郵件", "tiyklkinqanxbgXX", 587, "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"] = "10"; //設置作業中每個線程的優先順序 properties["quartz.threadPool.threadPriority"] = ThreadPriority.Normal.ToString(); // 遠程輸出配置 properties["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz"; properties["quartz.scheduler.exporter.port"] = "555"; //配置埠號 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; } } }