87

I am holding some information in static variables defined in page class (not in Global.asax). I only declare variable in code like:

protected static int SomeGlobalUnsecureID;
protected static string SomeGlobalUnsecureString;

and define the variable in PageLoad event. For example, I check ID from the database, if it's different from SomeGlobalUnsecureID, I update SomeGlobalUnsecureID and String from somewhere else, otherwise leave them as is. This is perfectly safe in my app. logic (i.e. those data are not secure, everybody can access them, no problem); only thing I want to accomplish is

  1. Hold the same amount of memory regardless of users connected

  2. Change if and only if persistent info is different from the one in 'memory' (because actually reading the string is time consuming for me.

Now, since I make the check in PageLoad, I have no problems in reloaded pages. However my page is full of WebMethods, and sometimes I see that the static variables are zeroed. And the strange part is; the session is still active even when the static variables are zeroed (so-> no server or app. pool restart etc.)

This is really strange for me. I assume that static variable will hold its value until the application (somehow) ends. But even the Session did not expire, the static variable is zeroed. What do you suggest? Is using application variables a better choice? All documents I've read on web suggest static variables instead of application variables, do I need to declare them somehow different?

Aristos
  • 66,005
  • 16
  • 114
  • 150
paul simmons
  • 5,568
  • 13
  • 51
  • 78
  • 1
    The declarations at the top of your question are *not* static, btw. – Andrew Barber Jan 18 '12 at 23:35
  • 1
    'define the variable in PageLoad event.' I think you mean initialize? Defining a variable is what you are doing when you write `protected static int Something;` – Carl G Feb 13 '13 at 22:59
  • "Now, since I make the check in PageLoad, I have no problems in reloaded pages." - this sounds like a race condition waiting to happen. I'd consider thread-safe lazy initialization instead. – millimoose Feb 14 '13 at 17:12
  • A static lass lasts till the next recycle. Put your variables in a static class the use it in others – Mbithy Mbithy Jul 26 '17 at 17:05

3 Answers3

117

Static variables persist for the life of the app domain. So the two things that will cause your static variables to 'reset' is an app domain restart or the use of a new class. In your case with static variables stored in an aspx Page class, you may be losing the static variables when ASP.NET decides to recompile the aspx Page into a new class, replacing the old page class with the new one.

For those reasons if the system decide to restart or replace the class (.NET doesn't kill or unload classes/assemblies in a running app domain) then your static variables will reset because you are getting a new class with the restart or replacement. This applies to both aspx Pages and classes in the App_Code folder

ASP.NET will replace a class if for any reason thinks that need to recompile it (see ASP.NET dynamic compilation).

You can't prevent the loss of static variables from an app domain restart, but you can try to avoid it from class replacement. You could put your static variables in a class that is not an aspx page and is not in the App_Code directory. You might want to place them on a static class somewhere in your program.

public static class GlobalVariables
{
    public static int SomeGlobalUnsecureID;
    public  static string SomeGlobalUnsecureString;
}

The static variables are per pool, that is means that if you have 2 pools that runs your asp.net site, you have 2 different static variables. (Web garden mode)

The static variables are lost if the system restarts your asp.net application with one of this way.

  1. the pool decide that need to make a recompile.
  2. You open the app_offline.htm file
  3. You make manual restart of the pool
  4. The pool is reach some limits that you have define and make restart.
  5. For any reason you restart the iis, or the pool.

This static variables are not thread safe, and you need to use the lock keyword especial if you access them from different threads.

Since an app restart will reset your statics no matter what, if you really want to persist your data, you should store the data in a database using custom classes. You can store information per-user in Session State with a database session state mode. ASP.NET Application State/Variables will not help you because they are stored in memory, not the database, so they are lost on app domain restart too.

Kevin
  • 74,910
  • 12
  • 133
  • 166
Aristos
  • 66,005
  • 16
  • 114
  • 150
  • what is the better approach for storing persistent application data like this, some kind of external caching store? – Daniel Powell Jan 19 '12 at 00:16
  • @DanielPowell Depend. In my program that I have many pools and many threads the common to all threads data saved on database. The common data to each application saved to a global static class. – Aristos Jan 19 '12 at 00:21
  • one final thing; i've created a static class named global and added properties in it. works ok in .cs code, but in aspx i cannot access global class with <%=global.someproperty%> altough they are in same namespace. is that normal? – paul simmons Jan 19 '12 at 00:37
  • @paulsimmons No you must be able to access it. - I make a test and I can access them. – Aristos Jan 19 '12 at 00:43
  • strange, in some parts of the code i cannot access. but adding the namespace name in the beginning solved it. as i said, even they are in same namespace – paul simmons Jan 19 '12 at 00:46
  • @paulsimmons I also make some test now to see if I can kill the class and the reset the static variables but I fail to verify it. I think that have to do with multi threads that iis create for your page for the users. Somewhere there the static variables mix up. – Aristos Jan 19 '12 at 00:49
  • 9
    @Aristos This may be an old question, but your answer is not accurate. If a class variable is static, it doesn't matter how many instance of this class you create and kill, this variable will still hold its value as long as its assembly remains loaded in memory. However, because IIS regularly recycles hosted applications, some assemblies get unloaded and then loaded again, causing loss of static variable data. Take a look at [this](http://blogs.msdn.com/b/tess/archive/2006/08/02/asp-net-case-study-lost-session-variables-and-appdomain-recycles.aspx) – Thomas C. G. de Vilhena Jul 16 '12 at 02:19
  • 1
    @ThomasC.G.deVilhena I say (agree) the same thing with you ? Didn't type it well ? Can you please edit my question and correct this part that you say ? – Aristos Jul 16 '12 at 07:30
  • 1
    I think the problem is that the static variables are defined in an aspx file (which must be a non-static class.) Besides an application restart (which wipes all static variables), IIS will also recompile aspx pages (when they are modified, or possibly for other reasons) and then load the new compiled assembly. The newly compiled aspx page/class is a new class with its own static variables. Switching the variables to a static class should prevent resetting except in case of application restart because now aspx recompilation does not occur for the class. – Carl G Feb 13 '13 at 23:30
  • As I understand IIS and ASP.NET, ASP.NET doesn't kill and recreate classes for aspx pages, instead it recompiles the aspx pages, loads the DLL containing the new compiled code, and then just uses the new class instead. The old class sticks around until application restart, but it will not be accessible in a page request because ASP.NET is using the newly compiled class. – Carl G Feb 13 '13 at 23:33
  • `or if create a new thread for the same page for two different users` I don't think this would be the cause, because threads share static memory in the same application domain. It's only the loading of a new DLL or a restart of the app domain that resets the statics. – Carl G Feb 13 '13 at 23:34
  • And I don't think there is such thing as `static global class`. There is just `static class`. – Carl G Feb 13 '13 at 23:35
  • @CarlG Is need a little more tests, because I am not sure how exaclty asp.net make the pages and return the results. Its more possible to kill and recreate the class of each page in each request, and its have many threads that do that work. Anyway, I need to focus more on some details to give an answer with facts. of course is you have many pools then I have proof that opens different threads for the same user, and the same user can read the same page with the one or the other thread. – Aristos Feb 14 '13 at 11:25
  • 1
    @ThomasC.G.deVilhena If you like to change some part of this answer to make it more accurate, please do so. – Aristos Feb 14 '13 at 11:32
  • 1
    @CarlG I suggest to you the same, if you like to change some part of this answer, or add some other aspects to make it more accurate please do so. – Aristos Feb 14 '13 at 11:33
  • Sounds like a huge memory leak. Leaving old classes in memory every time a page is edited and recompiled. – Triynko Sep 15 '15 at 14:59
  • @Triynko I do not know how you conclude that - there is not any memory leak. – Aristos Sep 15 '15 at 15:46
  • @Aristos it sounds like the pages are getting recompiled, and then both the new and the old DLL are in memory -- can you explain how the old DLL is cleaned up? -- I didn't think you could unload DLLs from an AppDomain (dynamically compiled or not). -- Anyway, this seems kind of annoying, I've not made any changes to a website, but somehow there are multiple versions of my static variables on the same server -- but this sounds like exactly what's happening. -- Is this documented anywhere? – BrainSlugs83 Feb 02 '16 at 20:37
  • @BrainSlugs83 Your site is probably runs on web garden, means that more than one process on your pool is handling your pages. The only solution is a file database in this case, or memory mapped files... I know, you probably use this static as cache for some db data... and they must be the same... – Aristos Feb 02 '16 at 21:56
  • @Aristos it's not for a cache, it's for a persistent connection to a remote Akka.NET actor cluster; it's pretty expensive to restart that connection (can't do it per request, etc.). And running two connections on the same front end sever is causing all sorts of headaches for me. Any advice? – BrainSlugs83 Feb 12 '16 at 11:18
  • 1
    @BrainSlugs83 No I do not have any advice. I have face similar problems and did not have find solutions. The programs runs in different memory spaces and the direct communication betwing them is not allowed... Maybe if you make a service and your program communicate with that service. The service is runs ones, the program (pools) can runs at the same times more than one... – Aristos Feb 12 '16 at 16:54
  • static class lasts till the next recycle. This was the solution – Mbithy Mbithy Jul 26 '17 at 17:04
  • @LordBlack Personally I did not make any recycle on the web app... I have made this part off. – Aristos Jul 26 '17 at 18:14
24

I think the following two points are also important for the lifetime of static variables:

1 - In your application pool's advanced settings check "Recycling" -> "Regular Time Interval (minutes)" setting. It's default value is 1740 which means in each 29 hours your static variables are lost because of recycling of your application pool. This setting is used for termination of possible memory leaks. I would not change this setting..

2 - In your application pool's advanced settings check "Process Model" -> "Idle Time-out (minutes)" setting. It's default value is 20 which means in each 20 minutes of inactivity in your application pool, the worker processes are terminated/suspended which will cause your static variables to be lost. This setting is used for freeing up resources when the application pool is not used in some amount of time. You can set it to 0 to disable the timeout.

yakya
  • 4,559
  • 2
  • 29
  • 31
  • 1
    Thank you. **Recycling** was the problem in my case. – Isaac Oct 07 '17 at 07:58
  • 1
    IMHO the default recycling settings should be changed for most applications as it "shifts" - I guess I like to know EXACTLY when the pool will recycle without having to think about it. – combatc2 Oct 10 '20 at 16:45
-13

Static variable is used to store the all the object for same value

protected void Page_Load(object sender, EventArgs e)
{
    sss s1, s2;
    s1 = new sss();
    s1.TotalMark = 10;
    s2 = new sss();
    s2.TotalMark = 20;
    sss.SchoolName = "St.Joseph's Hr.Sec.S"; //We can access through class and assign common to all
    s1.PrintData();
    s2.PrintData();
}

public class sss
{
    public static string SchoolName { set; get; }
    public int TotalMark { set; get; }
    public string StudentName{set;get;}
    public void PrintData()
    {
        Console.WriteLine(TotalMark);
        Console.WriteLine(SchoolName);
        Console.WriteLine(StudentName);
    }
}
  • 5
    Down voted, this answer is not related to the question. (The OP clearly understands how static variables are supposed to work. -- The question is why are they not working correctly.) -- Additionally the explanation is worded poorly. – BrainSlugs83 Feb 02 '16 at 20:40