時候會要求一個或者多個任務(wù)在一定的時間或者一定的時間間隔內(nèi)計劃進(jìn)行,比如定時備份或同步數(shù)據(jù)庫,定時發(fā)送電子郵件,定期處理用戶狀態(tài)信息,支付系統(tǒng)中定期同步異常賬單等等,我們稱之為計劃任務(wù)。實(shí)現(xiàn)計劃任務(wù)的方法也有很多,可以采用SQLAgent執(zhí)行存儲過程,采用Windows任務(wù)調(diào)度程序來實(shí)現(xiàn),也可以使用Windows服務(wù)來完成我們的計劃任務(wù),這些方法都是不錯的解決方案。但是,以上這些都需要有服務(wù)器的權(quán)限才能進(jìn)行,而對于虛擬主機(jī)客戶使用的Web應(yīng)用程序來說,這些方法實(shí)現(xiàn)起來并不是很簡單的,主機(jī)服務(wù)提供商或者不能直接提供這樣的服務(wù),或者需要你支付許多額外的費(fèi)用。 看過一些這方面的文章,發(fā)現(xiàn)有一個共同的缺點(diǎn):IIS運(yùn)行到一定時期,計劃任務(wù)就停止了。查找原因發(fā)現(xiàn)是IIS的應(yīng)用程序池定期回收導(dǎo)致計劃任務(wù)停止。本文的這個方法可以解決應(yīng)用程序池回收問題。 請看代碼:
Global.asax.cs
using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.SessionState; using System.Timers; using System.Net; using System.IO; using System.Text; using System.Threading; //手機(jī)主題:http://www. //Email:haolinks#163.com //Author:漫步甜蜜 namespace { public class Global : System.Web.HttpApplication {
protected void Application_Start(object sender, EventArgs e) { //定義定時器 System.Timers.Timer myTimer = new System.Timers.Timer(5000); myTimer.Elapsed += new ElapsedEventHandler(myTimer_Elapsed); myTimer.Enabled = true; myTimer.AutoReset = true; }
void myTimer_Elapsed(object source, ElapsedEventArgs e) { try { Log.SaveNote(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":AutoTask is Working!"); YourTask(); } catch (Exception ee) { Log.SaveException(ee); } }
void YourTask() { //在這里寫你需要執(zhí)行的任務(wù) }
protected void Application_End(object sender, EventArgs e) { Log.SaveNote(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + ":Application End!");
//下面的代碼是關(guān)鍵,可解決IIS應(yīng)用程序池自動回收的問題 Thread.Sleep(1000); //這里設(shè)置你的web地址,可以隨便指向你的任意一個aspx頁面甚至不存在的頁面,目的是要激發(fā)Application_Start //string url = "http://www.";手機(jī)主題 string url = "http://localhost:82/111.aspx"; HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url); HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse(); Stream receiveStream = myHttpWebResponse.GetResponseStream();//得到回寫的字節(jié)流
} } }
原理:Global.asax 可以是asp.net中應(yīng)用程序或會話事件處理程序,我們用到了Application_Start(應(yīng)用程序開始事件)和Application_End(應(yīng)用程序結(jié)束事件)。當(dāng)應(yīng)用程序開始時,啟動一個定時器,用來定時執(zhí)行任務(wù)YourTask()方法,這個方法里面可以寫上需要調(diào)用的邏輯代碼,可以是單線程和多線程。當(dāng)應(yīng)用程序結(jié)束時,如IIS的應(yīng)用程序池回收,讓asp.net去訪問當(dāng)前的這個web地址,本地測試的時候?qū)懕镜氐刂?,?A href="http://localhost:82/111.aspx">http://localhost:82/111.aspx,到正式生產(chǎn)環(huán)境,可以改成你的web地址,如手機(jī)主題:http://www.等。這里需要訪問一個aspx頁面,這樣就可以重新激活應(yīng)用程序。Log類是一個記錄日志的一個類,下面是測試時生成的日志信息: ================================================================ 2008-10-30 17:46:10:AutoTask is Working! 2008-10-30 17:46:15:AutoTask is Working! 2008-10-30 17:46:20:AutoTask is Working! 2008-10-30 17:46:23:Application End! 2008-10-30 17:46:29:AutoTask is Working! 2008-10-30 17:46:34:AutoTask is Working! 從日志中發(fā)現(xiàn),當(dāng)手動回收IIS的應(yīng)用程序池之后,計劃任務(wù)還在執(zhí)行,說明我們的目的達(dá)到了。 如果將Application_End中的代碼注釋掉,會發(fā)現(xiàn)Application End之后,計劃任務(wù)停止工作了,如下: ================================================================ 2008-10-30 18:01:34:AutoTask is Working! 2008-10-30 18:01:39:AutoTask is Working! 2008-10-30 18:01:44:AutoTask is Working! 2008-10-30 18:01:46:Application End!
局限性:可以解決應(yīng)用程序池自動或者手動回收,但是無法解決IIS重啟或者web服務(wù)器重啟的問題,當(dāng)然這種情況出現(xiàn)的時候不多,而且如果有人訪問你的網(wǎng)站的時候,又會自動激活計劃任務(wù)了。
|