在 web.config 中如下设定的 HttpModule 在 Web 应用启动时,偶尔会出现多个实例。在这些实例中,其中一个会保持下来,其它几个将在 n 分钟后自动 Dispose 掉。
<httpModules>
<add name="MyHttpModule" type= "My.Framework.MyHttpModule, My.Framework" />
</httpModules>
这个问题影响到在 HttpModule 中,不能无顾忌的使用静态变量。
比如,在 Dottext 0.96 中的 EventHttpModule 下面这样的写法是有问题的:
namespace Dottext.Framework.ScheduledEvents
{
/// <summary>
/// Summary description for EventModule.
/// </summary>
public class EventHttpModule: System.Web.IHttpModule
{
static Timer eventTimer;
public EventHttpModule()
{
}
#region IHttpModule Members
public void Init( System.Web.HttpApplication application )
{
if (eventTimer == null)
{
eventTimer = new Timer( new TimerCallback( ScheduledEventWorkCallback ),
application.Context, 60000, EventManager.TimerMinutesInterval * 60000 );
}
}
private void ScheduledEventWorkCallback( object sender )
{
try
{
EventManager.Execute();
}
catch (Exception ex)
{
LogManager.CreateExceptionLog( ex, "Failed ScheduledEventCallBack" );
}
}
public void Dispose()
{
eventTimer = null;
}
#endregion
}
}
看到这个代码,首先的问题是 eventTimer 没有被显性的 Dispose,查阅MSDN及试验证明,Timer 类型(无论是 System.Threading.Timer 还是 System.Timers.Timer)不做显性的 Dispose,其计时器事件还是会被响应的。
于是,在 eventTimer = null; 前面加上了 eventTimer.Dispose();
然后经过一些方法测试,就发现了本篇开头发现的问题。EventHttpModule 出现了两个实例,其中一个实例创建了一个 eventTimer 实例,另外一个实例中,eventTimer 没有再次创建。过了一段时间,其中一个 EventHttpModule 实例(应该是没有被正式引用的 EventHttpModule 实例)被 Dispose,eventTimer 被终止,另一个 EventHttpModule 中,eventTimer 当然也就失去了计时器作用。