More adventures in Web app threading

Responses in my last post about this were either, "Threading in a Web app isn't a good idea," or a lengthy example that works, but wasn't really what I was after. After looking a little harder, I realized the error of my ways. The goal was to launch a Timer from an HttpModule. This is where I started:

public void Init(HttpApplication application)
{
 myTimer = new Timer(new TimerCallback(this.TimerMethod), application.Context, 60000, 60000);
}

static Timer myTimer;

private void TimerMethod(object sender)
{
 HttpContext context = ((Application)sender).Context;
 MyClass.StaticMethod(context);
}

Then in the class being called by the timer, something like this:

public static void StaticMethod(HttpContext context)
{
   Cache cache = context.Cache;
}

The problem there was that the cache object was always null. So at some point someone on the asp.net forums suggested this to me:

public void Init(HttpApplication application)
{
 appHandle = GCHandle.Alloc(application.Context, GCHandleType.Normal);
 myTimer = new Timer(new TimerCallback(this.TimerMethod), application.Context, 60000, 60000);
}

static Timer myTimer;
protected GCHandle appHandle;

private void TimerMethod(object sender)
{
 HttpContext context = (HttpContext)appHandle.Target;
 MyClass.StaticMethod(context);
}

This did indeed work. I wasn't sure why, but I did get that it prevented the GC from disposing of the HttpContext object, which otherwise would die. After some toying around, mostly through chance Intellisense encounters, I arrived at this, which works as it should, without the GCHandler:

private void TimerMethod(object sender)
{
 HttpContext context = (HttpContext)sender;
 MyClass.StaticMethod(context);
}

...with the static method establishing the cache this way:

Cache cache = HttpRuntime.Cache;

What do you know, it works. Watching the output in the debugger, it keeps doing its thing, on and on and on. I'm not sure if the context object in the static method can access the Application object, but seeing as how I have the cache, that's more than adequate.

4 Comments

  • since it seems all you want is the Cache, which lives through any Context's, why dont you just reference the Cache at the beginning instead of all this potential problematic code?



    Init

    {

    MyStaticCache = HttpContext.Current.Cache;

    }



    because if you try to use the Context.Request or Context.Response you'll basically be in undefined territory...

  • What's problematic about it? The last version works and works fine.

  • Could you please state what the HttpModule does and what the timer has to do with it, because right now I don't get it. Seems like every minute you want to do something. How does it correlate to the current Request?

    In your previous post I assumed you where talking about doing an async "mailing" operation (from normal System.Web.UI.Page code), in which case the samples I provided were adequate (and the recommended way to pass objects to other threads).

  • It has nothing to do with the request. In fact, it doesn't even need to be about mailing something. The goal is was to be able to get the cache object from objects spawned to their own thread, whether that be via a page or from an HttpModule. The secondary goal of that was to get application configuration from web.config in these same objects. As I said, the last example works. To be more clear:



    // HttpModule

    public void Init(HttpApplication application)

    {

    myTimer = new Timer(new TimerCallback(this.TimerMethod), application.Context, 60000, 60000);

    }



    static Timer myTimer;



    private void TimerMethod(object sender)

    {

    HttpContext context = (HttpContext)sender;

    MyClass.StaticMethod(context);

    }





    // MyClass

    public static void StaticMethod(HttpContext context)

    {

    Cache cache = HttpRuntime.Cache;

    System.Configuration.Configuration config =

    System.Configuration.Configuration.GetWebConfiguration(context.Request.ApplicationPath);

    }

Comments have been disabled for this content.