公司项目有一个需求,就是需要定时的给一些用户发送邮件。本来想想蛮简单的,只需要在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来做事务,都用服务。