公司項目有一個需求,就是需要定時的給一些用戶發送郵件。本來想想蠻簡單的,只需要在Global.ascx中啟動一個定時器,然后定時執行這項任務就好了。可是運行的結果卻不是我想想中的那樣。我寫的代碼是這樣的:
private System.Timers.Timer m_timer; void Application_Start(object sender, EventArgs e) { m_timer = new System.Timers.Timer(60000);//設置間隔時間 m_timer.Enabled = true; m_timer.Elapsed += new System.Timers.ElapsedEventHandler(run); //開啟時鍾。 m_timer.Start(); }
原來這個定時器只有在網頁第一次被訪問的時候才能啟動,就是說網站在被重啟的時候還需要手動的訪問我的任意一個頁面來激活這個Timer,這就罷了吧,反正去重啟的人也是我,自己注意點也就是了。可是經過幾天的測試,發現這個定時器並沒有一直執行,到一定的時間,這個定時器就停止工作了。后來百度了一下,發現一種說法,就是當應用程序池被回收后,我們還需要再次激活這個Timer,而IIS默認的回收時間是29小時。算了,我也忍了,畢竟這個站是一直會被訪問的。重復激活就重復激活吧,只要程序能用,咱就將就一下咯。
又經過幾天的測試,還是發現Timer有事會停止工作,百度了一下,有人說是這樣的一個Timer對象,在對象池里面是沒有引用的。當垃圾回收機制啟動的時候,這個Timer也會被回收掉,不管你有沒有在RUN。看到這里我崩潰了,一個簡單的定時器遇到了這么多的問題,算了我們還是不用定時器,改用服務吧,這總該可以了吧,百度了一下,發現了一個管理服務的類,寫了一個測試頁面測試了一下,效果還不錯
測試頁面代碼:
protected void Page_Load(object sender, EventArgs e) { string serverName = "Monitoring"; string filePath = "C:\\Documents and Settings\\Administrator\\My Documents\\Visual Studio 2010\\Projects\\ServiceHelloWorld\\ServiceHelloWorld\\bin\\Debug\\ServiceHelloWorld.exe"; bool serviceIsExist = ServerHelper.DAL.ServiceHelper.ServiceExist(serverName); if (serviceIsExist) { Common.Common.LogManager.GetInstance().Debug("卸載"); ServerHelper.DAL.ServiceHelper.UnInstallService(filePath, serverName); Response.Write("卸載"); } else { // string serviceName = ""; Common.Common.LogManager.GetInstance().Debug("安裝"); ServerHelper.DAL.ServiceHelper.InstallService(filePath,serverName); Response.Write(serverName); Response.Write("安裝"); }
安裝服務的代碼:
/// <summary> /// 安裝服務 /// </summary> /// <param name="stateSaver"></param> /// <param name="filepath"></param> /// <param name="serviceName"></param> public static void InstallService(string filepath, string serviceName) { System.ServiceProcess.ServiceController service = new System.ServiceProcess.ServiceController(serviceName); if (!ServiceExist(serviceName)) { AssemblyInstaller myAssemblyInstaller = new AssemblyInstaller(); myAssemblyInstaller.UseNewContext = true; myAssemblyInstaller.Path = filepath; IDictionary stateSaver = new Hashtable(); stateSaver.Clear(); myAssemblyInstaller.Install(stateSaver); myAssemblyInstaller.Commit(stateSaver); myAssemblyInstaller.Dispose(); service.Start(); } else { if (service.Status != System.ServiceProcess.ServiceControllerStatus.Running && service.Status != System.ServiceProcess.ServiceControllerStatus.StartPending) { service.Start(); } } }
卸載服務的代碼:
/// <summary> /// 卸載服務 /// </summary> /// <param name="filepath"></param> /// <param name="serviceName"></param> public static void UnInstallService(string filepath, string serviceName) { try { if (ServiceExist(serviceName)) { AssemblyInstaller myAssemblyInstaller = new AssemblyInstaller(); myAssemblyInstaller.UseNewContext = true; myAssemblyInstaller.Path = filepath; myAssemblyInstaller.Uninstall(null); myAssemblyInstaller.Dispose(); } } catch (Exception ex) { throw new Exception("unInstallServiceError/n" + ex.Message); } }
有了這樣的一個方法,我就再也不會用Timer的方式來處理定時的事務了,而且據說大牛們都不用Timer來做事務,都用服務。