views:

1377

answers:

3

I have some ASP.NET web services which all share a common helper class they only need to instantiate one instance of per server. It's used for simple translation of data, but does spend some time during start-up loading things from the web.config file, etc. The helper class is 100% thread-safe. Think of it as a simple library of utility calls. I'd make all the methods shared on the class, but I want to load the initial configuration from web.config. We've deployed the web services to IIS 6.0 and using an Application Pool, with a Web Garden of 15 workers.

I declared the helper class as a Private Shared variable in Global.asax, and added a lazy load Shared ReadOnly property like this:

Private Shared _helper As MyHelperClass

Public Shared ReadOnly Property Helper() As MyHelperClass
    Get
        If _helper Is Nothing Then
            _helper = New MyHelperClass()
        End If
        Return _helper
    End Get
End Property

I have logging code in the constructor for MyHelperClass(), and it shows the constructor running for each request, even on the same thread. I'm sure I'm just missing some key detail of ASP.NET but MSDN hasn't been very helpful.

I've tried doing similar things using both Application("Helper") and Cache("Helper") and I still saw the constructor run with each request.

A: 

I 'v done something like this in my own app in the past and it caused all kinds of weird errors. Every user will have access to everyone else's data in the property. Plus you could end up with one user being in the middle of using it and than getting cut off because its being requested by another user.

No there not isolated.

Donny V.
+1  A: 

You can place your Helper in the Application State. Do this in global.asax:

  void Application_Start(object sender, EventArgs e)
  {
    Application.Add("MyHelper", new MyHelperClass());
  }

You can use the Helper that way:

  MyHelperClass helper = (MyHelperClass)HttpContext.Current.Application["MyHelper"];
  helper.Foo();

This results in a single instance of the MyHelperClass class that is created on application start and lives in application state. Since the instance is created in Application_Start, this happens only once for each HttpApplication instance and not per Request.

JRoppert
This would instantiate a new object on every single request--I think Bob's trying to get a single object *per server*.
Michael Haren
That's it exactly.
Bob King
A: 

It's not wise to use application state unless you absolutely require it, things are much simpler if you stick to using per-request objects. Any addition of state to the helper classes could cause all sorts of subtle errors. Use the HttpContext.Current items collection and intialise it per request. A VB module would do what you want, but you must be sure not to make it stateful.