简体   繁体   English

ASP.NET中的请求或服务器的静态类实例是唯一的吗?

[英]Are static class instances unique to a request or a server in ASP.NET?

On an ASP.NET website, are static classes unique to each web request, or are they instantiated whenever needed and GCed whenever the GC decides to disposed of them? 在ASP.NET网站上,是每个Web请求唯一的静态类,还是在需要时实例化它们并在GC决定处理它们时进行GC操作?

The reason I ask is because I've written some static classes before in C# and the behavior is different than I would have expected. 我问的原因是因为我之前在C#中编写了一些静态类,并且行为与我预期的不同。 I would have expected static classes to be unique to each request, but it doesn't seem like that is the case. 我希望静态类对每个请求都是唯一的,但似乎并非如此。

If they are not unique to each request, is there a way to allow them to be? 如果它们并非每个请求都是唯一的,那么有没有办法让它们成为现实?

UPDATE: 更新:
The answer driis gave me was exactly what I needed. 答案给了我正是我所需要的。 I was already using a singleton class, however it was using a static instance and therefore was being shared between requests even if the users were different which in this case was a bad thing. 我已经在使用单例类,但是它使用的是静态实例,因此即使用户不同,也在请求之间共享,在这种情况下这是一件坏事。 Using HttpContext.Current.Items solves my problem perfectly. 使用HttpContext.Current.Items完美地解决了我的问题。 For anyone who stumbles upon this question in the future, here is my implementation, simplified and shortened so that it easy to understand the pattern: 对于任何在将来偶然发现这个问题的人来说,这是我的实现,简化和缩短,以便易于理解模式:

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;
        }
    }
}

Your static classes and static instance fields are shared between all requests to the application, and has the same lifetime as the application domain. 静态类和静态实例字段在对应用程序的所有请求之间共享,并且与应用程序域具有相同的生命周期。 Therefore, you should be careful when using static instances, since you might have synchronization issues and the like. 因此,在使用静态实例时应该小心,因为您可能会遇到同步问题等。 Also bear in mind, that static instances will not be GC'ed before the application pool is recycled, and therefore everything that is referenced by the static instance, will not be GC'ed. 还要记住,在应用程序池被回收之前,静态实例不会被GC控制,因此静态实例引用的所有内容都不会被GC控制。 This can lead to memory usage problems. 这可能导致内存使用问题。

If you need an instance with the same lifetime as a request, I would suggest to use the HttpContext.Current.Items collection. 如果您需要与请求具有相同生命周期的实例,我建议使用HttpContext.Current.Items集合。 This is by design meant to be a place to store stuff that you need througout the request. 这是设计意味着存储您需要的东西的地方。 For nicer design and readability, you can use the Singleton pattern to help you manage these items. 为了获得更好的设计和可读性,您可以使用Singleton模式来帮助您管理这些项目。 Simply create a Singleton class that stores its instance in HttpContext.Current.Items . 只需创建一个Singleton类,将其实例存储在HttpContext.Current.Items (In my common library for ASP.NET, I have a generic SingletonRequest class for this purpose). (在我的ASP.NET公共库中,我有一个通用的SingletonRequest类用于此目的)。

Static members have a scope of the current worker process only, so it has nothing to do with requests, because different requests may or may not be handled by the same worker process. 静态成员只具有当前工作进程的范围,因此它与请求无关,因为同一工作进程可能会或可能不会处理不同的请求。

  • In order to share data with a specific user and across requests, use HttpContext.Current.Session. 为了与特定用户和请求共享数据,请使用HttpContext.Current.Session。
  • In order to share data within a specific request, use HttpContext.Current.Items. 要在特定请求中共享数据,请使用HttpContext.Current.Items。
  • In order to share data across the entire application, either write a mechanism for that, or configure IIS to work with a single process and write a singleton / use Application. 为了在整个应用程序中共享数据,要么为其编写机制,要么将IIS配置为使用单个进程并编写单例/使用应用程序。

By the way, the default number of worker processes is 1, so this is why the web is full of people thinking that static members have a scope of the entire application. 顺便说一句,默认的工作进程数是1,所以这就是为什么Web上充满了人们认为静态成员具有整个应用程序的范围的原因。

Since the types are contained in an app domain, I would expect static classes to be present as long as the app domain is not recycled, or if the request gets served by a different app domain. 由于类型包含在应用程序域中,因此只要应用程序域未被回收,或者请求由其他应用程序域提供,我就会希望存在静态类。

I can think of several ways to make objects specific to a particular request depends on what you want to do, for eg you could instantiate the object in Application.BeginRequest and then store it in HttpRequest object so that it can be accessed by all objects in the request processing pipeline. 我可以想到几种方法来使特定于特定请求的对象取决于您想要做什么,例如,您可以在Application.BeginRequest中实例化该对象,然后将其存储在HttpRequest对象中,以便所有对象都可以访问它。请求处理管道。

If they are not unique to each request, is there a way to allow them to be? 如果它们并非每个请求都是唯一的,那么有没有办法让它们成为现实?

Nope. 不。 Static members are owned by the ASP.NET process and shared by all users of the Web app. 静态成员由ASP.NET进程拥有,并由Web应用程序的所有用户共享。 You'll need to turn to other session management techniques such as session variables. 您需要转向其他会话管理技术,例如会话变量。

Normally static methods, properties and classes are common at the Application level. 通常,静态方法,属性和类在Application级别很常见。 As long as the application lives, they are shared. 只要应用程序存在,它们就会被共享。

You can specify a different behaviour by using the ThreadStatic attribute. 您可以使用ThreadStatic属性指定不同的行为。 In that case they will be specific to the current thread, which, I think, is specific for each request. 在这种情况下,它们将特定于当前线程,我认为这是针对每个请求的。
I would not advise this though as it seems overcomplicated. 虽然看起来过于复杂,但我不建议这样做。

You can use HttpContext.Current.Items to set stuff up for one request, or HttpContext.Current.Session to set stuff up for one user (across requests). 您可以使用HttpContext.Current.Items为一个请求设置内容,或者使用HttpContext.Current.Session为一个用户设置内容(跨请求)。

In general though, unless you have to use things like Server.Transfer , the best way is basically creating things once and then passing them explicitly via method invocation. 一般来说,除非你必须使用像Server.Transfer这样的东西,否则最好的方法是基本上创建一次,然后通过方法调用显式传递它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM