三分鐘掌握,使用Quqrtz.Net實現定時發送郵件

来源:https://www.cnblogs.com/terryK/archive/2019/10/16/11686134.html
-Advertisement-
Play Games

使用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;
        }
    }
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 學習路線圖往往是學習一樣技術的入門指南。網上搜到的Java學習路線圖也是一抓一大把。 今天我只選一張圖,僅此一圖,足以包羅Java後端技術的知識點。所謂不求最好,但求最全,學習Java後端的同學完全可以參考這張圖進行學習路線安排。 當然,有一些知識點是可選的,並不是說上面有的你都要會啦。我在復 ...
  • 阿裡面經 "阿裡中間件研發麵經" "螞蟻金服研發麵經" 崗位是研發工程師,直接找螞蟻金服的大佬進行內推。 我參與了阿裡巴巴中間件部門的提前批面試,一共經歷了四次面試,拿到了口頭offer。 然後我也參加了螞蟻金服中間件部門的面試,經歷了三次面試,但是沒有走流程,所以面試中止了。 最後我走的是螞蟻金服 ...
  • 最近由於工作原因,一直忙於公司的各種項目(大部份都是基於spring cloud的微服務項目),故有一段時間沒有與大家分享總結最近的技術研究成果的,其實最近我一直在不斷的深入研究學習Spring、Spring Boot、Spring Cloud的各種框架原理,同時也隨時關註著.NET CORE的發展 ...
  • 在C#中,我們可以通過 a==b 的形式來判斷兩個引用是否相等。然而,在其系統中,相等判斷是根據行為的不同而得到不同的結果:一方面,預設的值類型採用值比較的方式來判斷相等性;另一方面,預設的引用類型通過判斷兩個引用是否引用同一個對象而判斷相等性。此外,在C#中,可以通過重載某些函數和邏輯來達到改寫相... ...
  • 快速響應矩陣碼(下) 書接上回,繼續下半場。 糾錯碼 QR 碼採用糾錯演算法生成一系列糾錯碼字,添加在數據碼字序列之後,使得符號可以在遇到損壞時可以恢復。這就是為什麼二維碼即使有殘缺也可以掃出來。沒有殘缺創造殘缺也要把它掃出來,相信大家見過很多中間帶圖標的二維碼吧。 糾錯碼字可以糾正兩種類型的錯誤,拒 ...
  • 問題: 就是一個字元串呀,一個字元串,裡面的話有一個空格,有可能有連續空格,你遇到連續空格,把這個連續空格變成一個空格,一個空格地不處理。 代碼: 效果: ...
  • 問題: 已知excel表格前面26個是a到z,27是aa28是ab,以此類推,N是多少 代碼: 效果: ...
  • 類: 類是一個能存儲數據並執行代碼的數據結構。 類是邏輯相關的數據和函數的封裝,通常代表現實中或概念上的事物。 類的關鍵字:class 類的主要成員類型有:欄位:方法。 欄位: 欄位是屬於類的變數。 預設修飾符為private。 每種類型的預設值都是0;bool型為false;引用類型為null。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...