NavWin - Navigating Windows Programming 
   Home/ASP.NET/App Domain Recycling And Static Variables Login
  AppDomain Recycling And Static Variables - Web Application Design
The purpose of this web page is to alert new web site developers to a particular issue that is fairly unique to web applications (as opposed to desktop applications). If you build your web application incorrectly then you may have to spend a lot of time fixing it later. The worst part is that none of the issues that are discussed on this web page will have any impact when building and testing your web application. This is because your test application will be run on a single server and be loaded in memory all the time.

This issue affects any system that will be run on a hosted server. A hosted server will run many web sites at the same time on a single server and may also use multiple load balanced servers to manage a single web application. In order to allow all the web sites to run at the same time, all sharing the same limited RAM space, it is necessary to unload a web site if it is not actually doing anything and reload it the next time it needs to do something (such as serve a page request).

An ASP.NET web site will manage this concept by loading each web site into its own AppDomain object. If the AppDomain does not receive any page requests within a certain time period then it will be unloaded until a new page request is made. Once a page request is received then the AppDomain will be reloaded. However the problem is that everything is not restored back to its original state (thanks Microsoft)! If it was then there would be very little need to discuss AppDomains at all.

AppDomains and static variables
The critical information that is not preserved when an AppDomain is reloaded are the state of any static variables. Not only do these not get reset to their original state but they are also not re-initialised with their design time default values. They will always be given values like null, empty string and zero.

Using static variables is generally not considered good programming practice in any case. However, developers do use them and they are time savers in some circumstances. They can be particularly useful when used in conjunction with the [ThreadStatic] attribute to temporarily share information between functions that are invoked through multiple synchronous events (aka event driven spaghetti-code) (for example, as used by the dreadful PropertyGrid control from Microsoft).

As an aside, it is ironic that two concepts of the OOP methodology (namely event driven programming and inheritance) have probably produced some of the worst excesses of spaghetti code ever created by over enthusiastic programmers. OOP was specifically meant to overcome the tendency of developers to create global variable based spaghetti code through the use of encapsulation and yet it has spawned two concepts capable of far worse asynchronous spaghetti than simple functions ever could.

Anyway, for web sites you really do not want to use static variables to store information that is needed for the life of your application. For example, if you thought to use them to cache session information, then don't! They will be randomly reset to zero and you have no control over when this happens

Microsofts solution to this issue - The session object
Microsoft have provided the session object which can be used to safely store session information. This is stored out-of-process from the AppDomain so is loaded and unloaded independently. However, if you are running on a hosted server you may not have control over when this gets unloaded (i.e. when the session times out). You may also find that your user session gets redirected to other servers in the case of a load-balanced system. In this case you need to force the user session to always get redirected to the same server. You can see the basics of this idea discussed here

http://msdn.microsoft.com/en-us/library/ms525037.aspx  (Managing Sessions Across Multiple IIS Servers)

It is probably best to avoid the session object for a completely generic solution.

Saving the state of static variables - App Start and End events
If you want to use static variables (e.g. to act as a memory cache of information) then you can patch into the Application_Start and Application_End events that are available in the Global.Aspx page. However this is tricky to program because, while your first application instance is still being unloaded (and there is a 30 second period to do this in) then your next application instance may be re-loading!. This means you have got to handle the fact that the data store may be accessed concurrently by two different applications. This makes for complicated programming which is difficult to test.

Designing Stateless Applications
The most robust solution to this problem is to build your application so that you manage your own session data and load it on demand. So long as you do this then you will never be hit with any of the issues mentioned above. Each session can be given a unique id and you create a folder on your data server for the session information. Every request is initialised from the folder and session data written back to the folder. The only thing you need to manage is to occasionally clean up the temporary session folders after the session timeout, which you control.

Loading Application Data Quickly - Load-On Demand
If we take this further, then you will also realise that any data that is required to process a client request must also be loaded each time and cannot be saved in memory. If your web application data is small and self-contained then you can load the entire user database into memory in one go and process the request from memory and then discard it. However, if you have a large application database then you will need to design your data access to load objects on demand. Depending on your data usage you may need to load a single object at a time (i.e. one row of the database) or you may need to load multiple rows from the same table for more efficiency. SQL Server and Oracle do most of the caching for you and you can take advantage of the .NET DataSet objects to provide powerful wrappers which take advantage of this.

Can Static Variables Be Used In Some Circumstances?
There are certain circumstances when it is reasonable to use a static variable for a short period of time. This is when you can guarantee that the variable will not be reset. The specific time when this can be done is when serving a page request. An example of this is shown below.

In this case the client page has sent the current client time. Various low level business functions make use of the client time in order to manipulate the data. However due to a bad design decision, the application has been programmed to use the value DateTime.Now (i.e. the server date/time) and not the client date time.

The best option is probably to adjust the application so that the client time is passed around to all these low level functions using input parameters. However, this may not be convenient and may not really add anything useful in terms of application maintainability or readability. Another option is to store the time in a [ThreadStatic] variable so that it is available as a global variable to all the low level functions.

As the value is recalculated on each client page request you can be sure that the value is correct and has not been reset by the host system.