C# 静态类实例对于 ASP.NET 中的请求或服务器来说是唯一的吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/194999/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Are static class instances unique to a request or a server in ASP.NET?
提问by Dan Herbert
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. I would have expected static classes to be unique to each request, but it doesn't seem like that is the case.
我问的原因是因为我之前用 C# 编写了一些静态类,并且行为与我预期的不同。我原以为每个请求的静态类都是唯一的,但事实并非如此。
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. 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:
更新:
driis 给我的答案正是我所需要的。我已经在使用单例类,但是它使用的是静态实例,因此即使用户不同,它也会在请求之间共享,这在这种情况下是一件坏事。使用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;
}
}
}
采纳答案by driis
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. This can lead to memory usage problems.
您的静态类和静态实例字段在对应用程序的所有请求之间共享,并且与应用程序域具有相同的生命周期。因此,在使用静态实例时应该小心,因为您可能会遇到同步问题等。还要记住,在应用程序池回收之前,静态实例不会被 GC 处理,因此静态实例引用的所有内容都不会被 GC 处理。这可能会导致内存使用问题。
If you need an instance with the same lifetime as a request, I would suggest to use the HttpContext.Current.Items
collection. 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. Simply create a Singleton class that stores its instance in HttpContext.Current.Items
. (In my common library for ASP.NET, I have a generic SingletonRequest class for this purpose).
如果您需要一个与请求具有相同生命周期的实例,我建议使用该HttpContext.Current.Items
集合。这是设计上用来存储您在整个请求中需要的东西的地方。为了更好的设计和可读性,您可以使用单例模式来帮助您管理这些项目。只需创建一个单例类,将其实例存储在HttpContext.Current.Items
. (在我的 ASP.NET 公共库中,我有一个通用的 SingletonRequest 类用于此目的)。
回答by Sijin
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 e.g. 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 对象中,以便它可以被所有对象访问请求处理管道。
回答by rp.
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 allusers of the Web app. You'll need to turn to other session management techniques such as session variables.
不。静态成员归 ASP.NET 进程所有,并由Web 应用程序的所有用户共享。您需要求助于其他会话管理技术,例如会话变量。
回答by Sklivvz
Normally static methods, properties and classes are common at the Application
level. As long as the application lives, they are shared.
通常静态方法、属性和类在Application
级别上是常见的。只要应用程序存在,它们就会被共享。
You can specify a different behaviour by using the ThreadStatic
attribute. 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.
您可以使用该ThreadStatic
属性指定不同的行为。在这种情况下,它们将特定于当前线程,我认为这是特定于每个请求的。
我不建议这样做,因为它看起来过于复杂。
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
的东西,否则最好的方法基本上是创建一次,然后通过方法调用显式传递它们。
回答by Moshe Bixenshpaner
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.
- In order to share data within a specific request, use 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.
- 为了与特定用户和跨请求共享数据,请使用 HttpContext.Current.Session。
- 为了在特定请求中共享数据,请使用 HttpContext.Current.Items。
- 为了在整个应用程序中共享数据,要么为此编写一种机制,要么将 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,所以这就是为什么网络上到处都是认为静态成员具有整个应用程序范围的人的原因。