1

I am using the following code in the ASP.NET web forms Global.aspx page to count the number of current active users. It does work when I do local testing.

Understanding is that Application is an Application-level variable and can be accessed at the application level. So value stored in one session will be available in other sessions.

<%@ Application Language="C#" %>  
  
<script runat="server">  
  
    void Application_Start(object sender, EventArgs e)   
    {  
        // Code that runs on application startup  
        Application["TotalOnlineUsers"] = 0;  
    }  
      
    void Application_End(object sender, EventArgs e)   
    {  
        //  Code that runs on application shutdown  
  
    }  
          
    void Application_Error(object sender, EventArgs e)   
    {   
        // Code that runs when an unhandled error occurs  
  
    }  
  
    void Session_Start(object sender, EventArgs e)   
    {  
        // Code that runs when a new session is started  
        Application.Lock();  
        Application["TotalOnlineUsers"] = (int)Application["TotalOnlineUsers"] + 1;  
        Application.UnLock();  
    }  
  
    void Session_End(object sender, EventArgs e)   
    {  
        // Code that runs when a session ends.   
        // Note: The Session_End event is raised only when the sessionstate mode  
        // is set to InProc in the Web.config file. If session mode is set to StateServer   
        // or SQLServer, the event is not raised.  
        Application.Lock();  
        Application["TotalOnlineUsers"] = (int)Application["TotalOnlineUsers"] - 1;  
        Application.UnLock();  
    }  
         
</script>

But while going through this link https://learn.microsoft.com/en-us/dotnet/api/system.web.httpapplication?redirectedfrom=MSDN&view=netframework-4.8, it says that member variables can be used to store per-request data.

Based on this statement and below complete paragraph, there can be multiple instances of HttpApplication for a single application, if not application will be super slow as one HttpApplication instance can process only one request at one point in time

Because of this, each HttpApplication will have its own Application variable and the count will be saved at HttpApplication level.

Instances of the HttpApplication class are created in the ASP.NET infrastructure, not by the user directly. One instance of the HttpApplication class is used to process many requests in its lifetime. However, it can process only one request at a time. Thus, member variables can be used to store per-request data.

An application raises events that can be handled by custom modules that implement the IHttpModule interface or by event handler code that is defined in the Global.asax file. Custom modules that implement the IHttpModule interface can be put in the App_Code folder or in a DLL in the Bin folder.

So, to get the exact count without any chance of miscalculating, should I use static variables?

Nithin B
  • 601
  • 1
  • 9
  • 26

1 Answers1

1

I believe your code will work correctly, assuming you’re using InProc session state and aren’t running in a Web farm.

Confusingly, the word “application” can have three different meanings:

  1. Your Web application (that is, the whole Web site)
  2. One of the multiple HttpApplication instances that serve requests to your Web application
  3. The HttpApplication.Application property

When the documentation says that the Application property returns “the current state of an application,” it means your Web application, not an individual HttpApplication instance.

It’s true that if you add a member variable to your Global class (which inherits from HttpApplication), then the member variable won’t be shared across HttpApplication instances. But the Application property is special: it returns the same HttpApplicationState object no matter which HttpApplication instance you use to access the property. Hence, any values you add via the Application property will be shared across all HttpApplication instances. (And that’s why you must call Lock and UnLock to synchronize access; you wouldn’t need to do so if the HttpApplicationState object weren’t shared.)

Michael Liu
  • 52,147
  • 13
  • 117
  • 150
  • Thanks for the information. I got this doubt why Application.Lock(); and Application.UnLock(); is being used if it is instance level. Probable values are stored externally as you said. Just for clarification is "InProc" applicable for Application State Variable too. Anyway, I will test that as it never crossed my mind, and also I didn't read anywhere when I read about Application State Variable online. Session state mode is always mentioned only when the discussion is about Session Variable and not Application State Variable? – Nithin B Jan 25 '22 at 15:19
  • Application state is always stored within the process, regardless of the session state mode. But, as the comment in your code says, the Session_End event is only raised if you're using InProc session state, so if you're using StateServer or SQLServer session state, then the number of users will never be decremented. – Michael Liu Jan 25 '22 at 15:44