I am trying to use a System.Threading.Timer
to perform a task every five seconds in a Http Module and the timer just randomly stops firing:
using Bookbyte.IpFilter.Manager;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
namespace Bookbyte.IpFilter
{
public class IpFilterModule : ApplicationStartModuleBase
{
private static object lockObject = new object();
private static Timer timer;
private static IpFilterManager filterManager;
private static IEnumerable<string> blacklist;
private static IEnumerable<string> whitelist;
public override void OnInit(HttpApplication context)
{
context.BeginRequest += (object sender, EventArgs e) =>
{
var app = sender as HttpApplication;
if (app != null)
{
var ipAddress = app.Request.UserHostAddress;
if (!whitelist.Any(x => x == ipAddress))
{
if (blacklist.Any(x => x == ipAddress))
{
app.Context.Response.StatusCode = 404;
app.Context.Response.SuppressContent = true;
app.Context.Response.End();
return;
}
}
}
};
base.OnInit(context);
}
public override void OnStart(HttpApplication context)
{
filterManager = new IpFilterManager();
blacklist = new List<string>();
whitelist = new List<string>();
timer = new Timer(new TimerCallback((object sender) =>
{
lock (lockObject)
{
blacklist = filterManager.GetBlacklist();
whitelist = filterManager.GetWhitelist();
}
}), null, 0, 5000);
base.OnStart(context);
}
public override void Dispose()
{
timer.Dispose();
base.Dispose();
}
}
}
And the ApplicationStartModuleBase
:
using System.Web;
namespace Bookbyte.IpFilter
{
public abstract class ApplicationStartModuleBase : IHttpModule
{
private static volatile bool applicationStarted = false;
private static object applicationStartLock = new object();
public void Init(HttpApplication context)
{
if (!applicationStarted)
{
lock (applicationStartLock)
{
if (!applicationStarted)
{
this.OnStart(context);
applicationStarted = true;
}
}
}
this.OnInit(context);
}
public virtual void OnInit(HttpApplication context)
{
}
public virtual void OnStart(HttpApplication context)
{
}
public virtual void Dispose()
{
}
}
}
So I figured out the problem. The timer
was being disposed in the module when the run time would call Dispose
on the module.
public override void Dispose()
{
timer.Dispose();
base.Dispose();
}
Removing the call to timer.Dispose()
fixed my issues.