ASP.NET MVC How safe are static variables

19,111

Solution 1

Your code is not thread safe. You are sharing static variables between multiple requests which could potentially be executed by multiple threads. Bear in mind that the Dictionary<TKey, TValue> class that you are using as underlying storage is not a thread safe class meaning that your code could potentially crash very badly if you attempt to call the OnAppInit method concurrently from multiple threads. If on the other hand you are calling this OnAppInit static method only once inside your Application_Start event (which is guaranteed to run only once from a single thread) you are pretty safe to use it there.

This being said saying that static variables and methods are generally a bad idea in applications is not true. They are a bad idea if you don't know how to use them properly, or if you don't know how to synchronize the access to them if you need this to be done from concurrent threads. Writing thread-safe code is a very difficult subject and if you have fears to make it wrong (who doesn't when writing multithreaded applications such as an ASP.NET application?) simply do not share state like this. Use the well established places for this in an ASP.NET application:

  • Backend (could be a relational database for example)
  • Application State
  • Cache
  • Http Context State
  • Session State
  • Client cookies

Those places are specifically designed for storing state in an ASP.NET application (except the first one of course which could be used in any type of application).

Solution 2

The static variables will be shared between requests. Moreover they will be initialized when application starts, so if the AppDomain, thus application gets restarted, their values will be reinitialized.

Share:
19,111

Related videos on Youtube

williamsandonz
Author by

williamsandonz

Updated on September 15, 2022

Comments

  • williamsandonz
    williamsandonz over 1 year

    I want to ensure my website is capable of being hosted on the cloud in the future and also that it can handle a lot of requests.

    How safe are static variables?

    Are they unsafe because separate requests by separate users are actually sharing these static variables? Or is it because if you spread the site over threads/sharding or similar, (to handle high loads) the threads are sharing the static variables?

    Mainly I have helper classes, with static properties, should I change this architecture so that I instead create an instance of each class and access the instances?

    E.G Here is a sample of what I am doing:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Mvc.Mailer;
    
    namespace MVCWebsite.Helpers
    {
            public class AppSettings
            {
                    public static void OnAppInit()
                    {
                            //General
                            AppName = "MyApp";
                            DesktopBaseURLs = new Dictionary<string, string>();
                            DesktopBaseURLs.Add("dev", "localhost:50560");
                            DesktopBaseURLs.Add("test", "www.test.whatever.com");
                            DesktopBaseURLs.Add("live", "www.whatever.com");
                            MobileBaseURLs = new Dictionary<string, string>();
                            MobileBaseURLs.Add("dev", "m.local.whatever.com");
                            MobileBaseURLs.Add("test", "m.test.whatever.com");
                            MobileBaseURLs.Add("live", "m.whatever.com");
    
                            //Emails
                            EmailHostName = AppName + ".com"; //For the moment atleast
                            NoReplyEmailAddress = "no-reply@" + EmailHostName.ToLower();
                            SupportEmailAddress = "support@" + EmailHostName.ToLower();
                            ErrorEmailAddress = "errors@" + EmailHostName.ToLower();
    
                            //Resources
                            TempFileURL = "/content/temp/";
                            UserDataURL = "/content/user-content/";
                            ProfilePicturesURL = UserDataURL + "profile-pictures/";
    
                            var a = GlobalHelper.GetURLAsServerPath(ProfilePicturesURL);
                            var b = a;
    
                    }
    
                    //General
                    public static string AppName { get; set; }
                    public static Dictionary<string, string> DesktopBaseURLs;
                    public static Dictionary<string, string> MobileBaseURLs;
    
                    //Emails
                    public static string EmailHostName { get; set; }
                    public static string NoReplyEmailAddress { get; set; }
                    public static string SupportEmailAddress { get; set; }
                    public static string ErrorEmailAddress { get; set; }
    
                    //Resources
                    public static string UserDataURL { get; set; }
                    public static string TempFileURL { get; set; }
                    public static string ProfilePicturesURL { get; set; }
    
                    //Methods
                    public static void SetAppURL()
                    {
    
                    }
            }
    }
    
  • Dmitry Efimenko
    Dmitry Efimenko over 11 years
    could you explain a bit more... what do you mean "your code could potentially crash very badly if you attempt to call the OnAppInit method concurrently from multiple threads"? What exactly could go wrong with this method?
  • Darin Dimitrov
    Darin Dimitrov over 11 years
    Well this method is modifying a local static variable which is of type Dictionary. As I said in my answer this type is not thread-safe. So for example the first thread will assign some value to the dictionary and start adding values to it when another thread will simply assign it to a new dictionary loosing all values that the first thread might have saved so far. This code should never be called from multiple threads.
  • williamsandonz
    williamsandonz over 11 years
    Thanks again Darin! Then I will either store the instances I create in a global object for easy accessing or I will just have a static Get() methods in each class which returns the only instance. That should fix it. :)
  • williamsandonz
    williamsandonz over 11 years
    Darin, Just realized I can't use Get() to return a static instance of the class, cause that would create the same problem, where shall I store my new non-static variables? Thinking as instance properties on some sort of instance of a global class....?
  • Darin Dimitrov
    Darin Dimitrov over 11 years
    No, don't be thinking in terms of any variables. Don't be thinking in terms of classes or variables (be it static or not). Think in terms of the storage scopes I have listed in my answer and which are available for you in an ASP.NET application. So to repeat them: Backend, Application State, Cache, Http Context, Session, Client Cookies.
  • williamsandonz
    williamsandonz over 11 years
    Thanks Darin, I'll do some reading and get my head around this one. :)
  • Yasser Sinjab
    Yasser Sinjab almost 8 years
    Will it be thread-safe if this static variable is used in my application for reading only?