2008-10-12 57 views
155

在ASP.NET网站上,是每个Web请求唯一的静态类,还是在GC决定处置它们时随时需要GC和GC进行实例化?ASP.NET中的请求或服务器是静态类实例吗?

我之所以这样问是因为我在C#编写之前一些静态类和行为是不同的,比我本来期望。我希望静态类对每个请求都是唯一的,但似乎并不是这样。

如果它们不是每个请求所特有的,有没有办法让它们成为?

更新:
答案驱动器给了我正是我所需要的。我已经使用了一个单例类,但它使用的是一个静态实例,因此即使用户不同,在这种情况下是不好的,也会在请求之间共享。使用HttpContext.Current.Items完美解决了我的问题。对于任何人谁在将来出现此问题失蹄,这里是我的实现,简化和缩短,使得它很容易理解的模式:

using System.Collections; 
using System.Web; 

public class GloballyAccessibleClass 
{ 
    private GloballyAccessibleClass() { } 

    public static GloballyAccessibleClass Instance 
    { 
     get 
     { 
      IDictionary items = HttpContext.Current.Items; 
      if(!items.Contains("TheInstance")) 
      { 
       items["TheInstance"] = new GloballyAccessibleClass(); 
      } 
      return items["TheInstance"] as GloballyAccessibleClass; 
     } 
    } 
} 
+0

只是一个头:如果你重定向你的请求,比如说,用'filterContext.Result = new RedirectResult(...)`,你会失去你的项目,因为将会创建一个新的HttpContext。更多细节在这里:https://stackoverflow.com/questions/16697601/response-redirect-does-not-preserve-httpcontext-current-items – 2018-03-01 18:22:30

回答

119

您的静态类和静态实例字段所有请求的应用程序之间共享,并具有相同的寿命作为应用程序域。因此,使用静态实例时应该小心,因为您可能有同步问题等。还要记住,在应用程序池回收之前,静态实例不会被GC化,因此静态实例引用的所有内容都不会被GC化。这可能会导致内存使用问题。

如果您需要的生存期的请求的情况下,我会建议使用HttpContext.Current.Items集合。这是设计的目的是为了存储你需要通过请求的东西。为了更好的设计和可读性,您可以使用Singleton模式来帮助您管理这些项目。只需创建一个Singleton类,将其实例存储在HttpContext.Current.Items中。 (在我用于ASP.NET的通用库中,为此我有一个通用的SingletonRequest类)。

+2

你能提供您Singleton模式涉及`HttpContext.Current.Items`的样本? – Airn5475 2011-08-25 20:23:38

+0

有关我的情况的更多详细信息:在我的Web应用程序中,用户将运行使用共享类属性的代码类库。我希望这个属性是用户特定的,但我不想把这个属性交给不同的函数。你提到的设计能否正确处理? – Airn5475 2011-08-25 20:40:59

11

由于类型都包含在一个应用程序域,我希望静态类只要应用程序域未被回收,或者如果请求由不同的应用程序域提供服务,就会出现。

我能想到的几种方法,使特定对象的特定要求取决于你想做的事,例如用于什么您可以在Application.BeginRequest中实例化对象,然后将其存储在HttpRequest对象中,以便它可以被请求处理管道中的所有对象访问。

4

如果他们不是唯一的每个请求,是有办法让他们呢?

没有。静态成员由ASP.NET进程拥有,并由所有用户共享。您需要转向其他会话管理技术,例如会话变量。

0

通常的静态方法,属性和类是在Application水平普遍。只要应用程序存在,它们就会共享。

您可以使用ThreadStatic属性指定不同的行为。在这种情况下,它们将特定于当前线程,我认为这是特定于每个请求的线程。
我不会建议这个,因为它似乎过于复杂。

您可以使用HttpContext.Current.Items为一个请求设置填充内容,或者使用HttpContext.Current.Session为一个用户设置填充内容(跨请求)。

一般来说,除非必须使用诸如Server.Transfer之类的东西,否则最好的方法是基本创建一次,然后通过方法调用显式传递它们。

16

静态成员仅具有当前工作进程的范围,因此它与请求无关,因为不同的请求可能会或可能不会由同一个工作进程处理。

  • 为了与特定用户和跨请求共享数据,请使用HttpContext.Current.Session。
  • 为了在特定请求中共享数据,请使用HttpContext.Current.Items。
  • 为了在整个应用程序共享数据,或者写为一个机构,或者配置IIS与单个处理工作,并写一个单/用途中的应用。

顺便说一句,工作进程的默认数量是1,所以这就是为什么网络充满了人们认为静态成员具有整个应用程序的范围。