1

我在 ASP.NET Web 表单 Global.aspx 页面中使用以下代码来计算当前活动用户的数量。当我进行本地测试时,它确实有效。

理解是Application是Application级别的变量,可以在应用级别访问。因此,存储在一个会话中的值将在其他会话中可用。

<%@ 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>

但是在通过此链接https://docs.microsoft.com/en-us/dotnet/api/system.web.httpapplication?redirectedfrom=MSDN&view=netframework-4.8时,它表示成员变量可用于存储 per-请求数据

基于此声明和下面的完整段落,单个应用程序可以有多个 HttpApplication 实例,如果没有,应用程序将非常慢,因为一个 HttpApplication 实例在一个时间点只能处理一个请求

因此,每个 HttpApplication 都有自己的 Application 变量,并且计数将保存在 HttpApplication 级别。

HttpApplication 类的实例是在 ASP.NET 基础结构中创建的,而不是由用户直接创建的。HttpApplication 类的一个实例用于在其生命周期内处理许多请求。但是,它一次只能处理一个请求。因此,成员变量可用于存储每个请求的数据。

应用程序引发的事件可由实现 IHttpModule 接口的自定义模块或由 Global.asax 文件中定义的事件处理程序代码处理。实现 IHttpModule 接口的自定义模块可以放在 App_Code 文件夹中,也可以放在 Bin 文件夹中的 DLL 中。

那么,为了得到准确的计数而不会有任何错误计算的机会,我应该使用静态变量吗?

4

1 回答 1

1

我相信您的代码可以正常工作,假设您使用的是 InProc 会话状态并且没有在 Web 场中运行。

令人困惑的是,“应用程序”一词可以具有三种不同的含义:

  1. 您的 Web 应用程序(即整个网站)
  2. 向您的 Web 应用程序提供请求的多个HttpApplication实例之一
  3. HttpApplication.Application属性_

当文档说 Application 属性返回“应用程序的当前状态”时,它表示您的 Web 应用程序,而不是单个 HttpApplication 实例。

确实,如果将成员变量添加到 Global 类(继承自 HttpApplication),那么该成员变量将不会在 HttpApplication 实例之间共享。但是 Application 属性很特殊:无论您使用哪个 HttpApplication 实例来访问该属性,它都会返回相同的 HttpApplicationState 对象。因此,您通过 Application 属性添加的任何值都将在所有 HttpApplication 实例之间共享。(这就是为什么您必须调用 Lock 和 UnLock 来同步访问;如果 HttpApplicationState 对象未共享,则不需要这样做。)

于 2022-01-23T18:36:59.377 回答