Multithreading and ASP.NET Application State

Monday, January 12, 2004
Each ASP.NET application has exactly one instance of HttpApplicationState. The single instance (often called the Application object) is an ideal place to store global variables. For a good introduction of using the Application object to store state, see the .NET Framework Developer’s Guide. As the guide points out, you should always consider the impact of using global variables. This article will concentrate on scalability impacts.

Here is one important tip in the guide:

Despite these issues, well-designed application-level variables can be very powerful in Web applications. You can do a one-time (or infrequent) loading and calculation of information and then use application state to cache it for speedy, in-memory access during later Web requests.

The key phrase is infrequent loading. As noted in the HttpApplicationState class documentation, the Application object is safe for multithreaded operations. This statement implies thread synchronization is built in. Take a look at the Get method in a decompiler and you’ll see the following.


public object Get(string name)
{ 
    object obj1;
    obj1 = null;
    this._lock.AcquireRead();
    try
    {
        obj1 = base.BaseGet(name);
    }
    finally
   {
         this._lock.ReleaseRead();
    }
    return obj1; 
}

The Application object uses some form of a single writer, multiple reader lock to synchronize access to application state. Take a look at the Set method next:


public void Set(string name, object value)
{ 
    this._lock.AcquireWrite();
    try
   {
        base.BaseSet(name, value);
    }
    finally
   {
        this._lock.ReleaseWrite();
    }
}

A reader writer lock allows multiple threads to read application state, but only a single thread to write to application state. Whenever you perform a Set operation, the write lock acquired will block all other writers and all other readers. This is not terribly important since a Set method should finish the job very quickly and release the lock, but if you are under an extreme load it is one area to be careful and try not to abuse.

The Application object also has a Lock method to synchronize access to application state. The Lock method will aquire a writer lock.The Lock is ideal to use when you need to Set more than one application variable as an atomic operation. In other words, you do not want to take the chance of a reader fetching values from application state while you are in the middle of changing two dependant variables with two Set operations. Once again, performing two Set operations should be a relatively quick operation, just do not abuse the privilege.

You want to try at all cost to avoid expensive operations while you have an application lock acquired. I’ve seen logging solutions where activity is recorded to a text file on the web server. The application synchronized access to the text file using Application.Lock. This solution will work, but make sure you test the solution with the demand and stresses that you expect to have in production because as the demand on your web application grows, this sort of solution can become a bottleneck. A more scalable solution would be to log activity in a database table, as the locks are taken care of by an efficient database engine. If you have no other choice than a single text file solution, consider keeping the activity log in memory. Start a timer during the Application_OnStart event (in global.asax) to flush the contents to a file every few minutes.


by Scott Allen (scott @ OdeToCode.com)

Resources

Application State : .NET Framework Developer's Guide

Using Session and Application Objects in ASP .NET : MSDN Magazine

HOW TO: Store Data in Application Scope by Using ASP.NET and Visual Basic .NET

by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!