是否按请求隔离Global.asax中的共享/静态变量?

时间:2020-03-05 18:53:23  来源:igfitidea点击:

我有一些ASP.NET Web服务,它们都共享一个公共的帮助程序类,它们仅需要实例化每个服务器的一个实例。它用于简单的数据转换,但在启动过程中确实要花费一些时间从web.config文件等中加载内容。helper类是100%线程安全的。可以将其视为实用程序调用的简单库。我会在类上共享所有方法,但是我想从web.config加载初始配置。我们已经将Web服务部署到IIS 6.0,并使用了具有15个工作人员的Web Garden的应用程序池。

我在Global.asax中将helper类声明为Private Shared变量,并添加了如下所示的延迟加载Shared ReadOnly属性:

Private Shared _helper As MyHelperClass

Public Shared ReadOnly Property Helper() As MyHelperClass
    Get
        If _helper Is Nothing Then
            _helper = New MyHelperClass()
        End If
        Return _helper
    End Get
End Property

我在MyHelperClass()的构造函数中记录了代码,它显示了构造函数针对每个请求运行,即使在同一线程上。我确定我只是缺少ASP.NET的一些关键细节,但是MSDN并没有太大帮助。

我已经尝试使用Application(" H​​elper")和Cache(" Helper")来做类似的事情,但我仍然看到构造函数随每个请求运行。

解决方案

回答

过去,我在自己的应用程序中做了类似的事情,这引起了各种奇怪的错误。
每个用户都可以访问该属性中其他所有人的数据。另外,我们可能最终会导致一个用户正在使用它,而不是因为另一个用户请求而被切断。

没有那里没有孤立。

回答

我们可以将助手放在"应用程序状态"中。在global.asax中执行以下操作:

void Application_Start(object sender, EventArgs e)
  {
    Application.Add("MyHelper", new MyHelperClass());
  }

我们可以通过以下方式使用帮助器:

MyHelperClass helper = (MyHelperClass)HttpContext.Current.Application["MyHelper"];
  helper.Foo();

这将导致MyHelperClass类的单个实例,该实例在应用程序启动时创建并处于应用程序状态。由于实例是在Application_Start中创建的,因此对于每个HttpApplication实例仅发生一次,而不是针对每个Request一次。

回答

除非绝对需要,否则使用应用程序状态是不明智的,如果坚持使用每个请求的对象,事情会简单得多。在帮助器类中添加任何状态都可能导致各种细微的错误。使用HttpContext.Current项目集合并根据请求初始化它。 VB模块可以完成我们想要的操作,但是我们必须确保不要使其具有状态。