Share via


Does ASP.NET magically handle thread safety for you?

The answer is NO.  It does not.   There are a few things you must be aware of when creating ASP.NET applications.

I ran some experiments where I intentionally set random values into different types of variables, and then slept for a random amount of time in the web service before returning the same variable to the caller.  Then I hammered the web service with hundreds of simulataneous requests.   It was pretty easy to see which variables were thread safe in this context, and which ones weren't.  The non thread-safe variables had a different value by the end of the function more than 50% of the time.  The safe variables were always the same regardless of how many threads I had running.

Note that the behavior appeared to be the same regardless of whether you are using IIS or the ASP.NET development server, and regardless of whether you are running retail or debug.

Here is the logic behind the threading model.   ASP.NET creates a thread pool for your web application.  Your class is instantiated once for each thread, and requests are queued on a per thread basis, your method will not be re-entered while it is executing.  So doesn't this solve everything?  Not quite.

Referring to the code below, the following types of variables are OK to use in ASP.NET:

  • Local variables inside a method
  • Member variables in your WebService class
  • Member variables in a helper class that is local to your method.
  • Member variables in a helper class that is referenced as a member inside your WebService class
  • The user's session.   (Session storage appears to be local to the thread)

The following types of variables are NOT thread safe and must be locked with the "lock" command or avoided if you want to ensure they won't change out from under you.

  • Static variables in your WebService class
  • A static reference to a helper class that contains member variables
  • A helper class that contains a static variable
  • the application value collection.

Here is a code view of the above:

    public class Service1 : System.Web.Services.WebService

    {

        int MEMBER_VARIABLE = 0;

        static int STATIC_VARIABLE = 0;

        helper MEMBER_HELPER = new helper();

        static helper STATIC_HELPER = new helper();

        class helper

        {

            public int HELPER_MEMBER_VARIABLE = 0;

            public static int HELPER_STATIC_VARIABLE = 0;

        }

        [WebMethod(EnableSession = true)]

        public int LocalVariable(int value)

        {

            helper LOCAL_HELPER = new helper();

            // THREAD SAFE 

            int LOCAL_VARIABLE = value;                    

MEMBER_VARIABLE = value;

            LOCAL_HELPER.HELPER_MEMBER_VARIABLE = value;

            MEMBER_HELPER.HELPER_MEMBER_VARIABLE = value;

            Session["Hello"] = value;

// NOT THREAD SAFE 

STATIC_VARIABLE = value;                       

            STATIC_HELPER.HELPER_MEMBER_VARIABLE = value;

            helper.HELPER_STATIC_VARIABLE = value;

            Application["Hello"] = value;

        }

               

    }

 Hopefully this is helpful to you.   If you have any questions related to this, please let me know and I'll dig up the answers!