因為項目中需要每月/每天建表,每天進行一些統計,所以封裝了一個類庫進行使用。
一、使用說明:
1. 把要執行的任務新建一個類放到本Web項目中,可以放在任意位置,建議放在AutoTask 文件夾下 2. 對該類應用屬性 AutoTask 如下所示 [AutoTask(EnterMethod = "StartTask", IntervalSeconds = 86400, StartTime = "2016-12-28 00:00:00")] 說明:EnterMethod 是任務入口,IntervalSeconds 是執行間隔,StartTime 是開始執行時間 如果設置IntervalSeconds 為空或0 ,則該任務只啟動時執行一次,忽略后面的start Time 參數 如果沒有設置StartTime ,則該任務啟動時立刻開始執行,按照間隔時間,每隔IntervalSeconds 秒執行一次。 如果StartTime 大於當前日期,則任務從StartTime 開始執行。 如果StartTime 小於當前日期,則從 StartTime + IntervalSecondes*n 開始執行,n為使該表達式大於DateTime.Now 的最小值。 3. 由此可以實現所有的定時功能。 如指定 每小時執行,則設置IntervalSeconds=3600,每天執行則設置IntervalSeconds=86400 若設置每天 0 點執行,則可以設置StartTime = "xxxx-xx-xx 00:00:00",IntervalSeconds=86400 若設置每周二晚上23 點執行 ,則可以設置StartTime = "xxxx-xx-xx 23:00:00",IntervalSeconds=604800 //86400*7 ,xxxx-xx-xx 可以設置為以前一個周二的日期 若設置每月,每年指定日期,則可以設置每天執行,然后在執行的代碼里進行判斷,判斷日期是否是指定的日期,為保證易用性,本類庫不進行擴展
二、源碼說明:
1. 在Global.asax.cs Application_Start中添加如下代碼
AutoTaskAttribute.RegisterTask();
添加Application_End 方法,解決IIS應用程序池自動回收的問題
protected void Application_End(object sender, EventArgs e) { //下面的代碼是關鍵,可解決IIS應用程序池自動回收的問題 Thread.Sleep(1000); //這里設置你的web地址,可以隨便指向你的任意一個aspx頁面甚至不存在的頁面,目的是要激發Application_Start
//我這里是一個驗證token的地址。 string url = System.Configuration.ConfigurationManager.AppSettings["tokenurl"]; HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url); HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse(); Stream receiveStream = myHttpWebResponse.GetResponseStream();//得到回寫的字節流 }
2. 把該類文件添加到項目中
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; using System.Web; using WebMVC.Utils; namespace WebMVC.Filters { /// <summary> /// Author:BigLiang(lmw) /// Date:2016-12-29 /// </summary> [AttributeUsage(AttributeTargets.Class)] public class AutoTaskAttribute : Attribute { /// <summary> /// 入口程序 /// </summary> public string EnterMethod { get; set; } /// <summary> /// 執行間隔秒數(未設置或0 則只執行一次) /// </summary> public int IntervalSeconds { get; set; } /// <summary> /// 開始執行日期 /// </summary> public string StartTime { get; set; } //保留對Timer 的引用,避免回收 private static Dictionary<AutoTaskAttribute, System.Threading.Timer> timers = new Dictionary<AutoTaskAttribute, System.Threading.Timer>(); /// <summary> /// Global.asax.cs 中調用 /// </summary> public static void RegisterTask() { new Task(() => StartAutoTask()).Start(); } /// <summary> /// 啟動定時任務 /// </summary> private static void StartAutoTask() { var types = Assembly.GetExecutingAssembly().ExportedTypes.Where(t => Attribute.IsDefined(t, typeof(AutoTaskAttribute))).ToList(); foreach (var t in types) { try { var att = (AutoTaskAttribute)Attribute.GetCustomAttribute(t, typeof(AutoTaskAttribute)); if (att != null) { if (string.IsNullOrWhiteSpace(att.EnterMethod)) { throw new Exception("未指定任務入口!EnterMethod"); } var ins = Activator.CreateInstance(t); var method = t.GetMethod(att.EnterMethod); if (att.IntervalSeconds > 0) { int duetime = 0; //計算延時時間 if (string.IsNullOrWhiteSpace(att.StartTime)) { duetime = 1000; } else { var datetime = DateTime.Parse(att.StartTime); if (DateTime.Now <= datetime) { duetime = (int)(datetime - DateTime.Now).TotalSeconds * 1000; } else { duetime = att.IntervalSeconds * 1000 - ((int)(DateTime.Now - datetime).TotalMilliseconds) % (att.IntervalSeconds * 1000); } } timers.Add(att,new System.Threading.Timer((o) => { method.Invoke(ins, null); }, ins, duetime, att.IntervalSeconds * 1000)); } else { method.Invoke(ins, null); } } } catch (Exception ex) { //LogHelper.Error(t.FullName + " 任務啟動失敗", ex); } } } } }
3. 使用示例
/// <summary> /// 測試任務,每10分鍾執行一次 /// </summary> [AutoTask(EnterMethod = "StartTask", IntervalSeconds = 600, StartTime = "2016-12-28 10:45:00")] public class TestTask { /// <summary> ////// </summary> public static void StartTask() { LogHelper.Info("定時任務啟動成功!"); LogHelper.Info("定時任務執行完畢!"); } }
這是我的框架中關於定時任務的一塊,以后會把整個框架分享出來。