Sind statische Klasseninstanzen für eine Anforderung oder einen Server in ASP.NET eindeutig?

182

Sind statische Klassen auf einer ASP.NET-Website für jede Webanforderung eindeutig oder werden sie bei Bedarf instanziiert und bei jeder Entscheidung des GC, sie zu entsorgen, überprüft?

Der Grund, den ich frage, ist, dass ich zuvor einige statische Klassen in C # geschrieben habe und das Verhalten anders ist, als ich erwartet hätte. Ich hätte erwartet, dass statische Klassen für jede Anforderung eindeutig sind, aber das scheint nicht der Fall zu sein.

Wenn sie nicht für jede Anfrage eindeutig sind, gibt es eine Möglichkeit, dies zuzulassen?

UPDATE:
Die Antwort, die driis mir gab, war genau das, was ich brauchte. Ich habe bereits eine Singleton-Klasse verwendet, jedoch eine statische Instanz, und wurde daher von Anforderungen gemeinsam genutzt, auch wenn die Benutzer unterschiedlich waren, was in diesem Fall eine schlechte Sache war. Die Verwendung HttpContext.Current.Itemslöst mein Problem perfekt. Für alle, die in Zukunft auf diese Frage stoßen, ist hier meine Implementierung, vereinfacht und verkürzt, damit das Muster leicht zu verstehen ist:

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;
        }
    }
}
Dan Herbert
quelle
Nur ein filterContext.Result = new RedirectResult(...)Hinweis : Wenn Sie Ihre Anfrage beispielsweise umleiten, verlieren Sie Ihre Artikel, weil ein neuer HttpContext erstellt wird. Weitere Details hier: stackoverflow.com/questions/16697601/…
Reuel Ribeiro
Eine verwandte Frage mit einer guten Antwort finden Sie unter stackoverflow.com/q/5219431 .
Theophilus

Antworten:

146

Ihre statischen Klassen und statischen Instanzfelder werden von allen Anforderungen an die Anwendung gemeinsam genutzt und haben dieselbe Lebensdauer wie die Anwendungsdomäne. Daher sollten Sie bei der Verwendung statischer Instanzen vorsichtig sein, da möglicherweise Synchronisierungsprobleme und dergleichen auftreten. Beachten Sie auch, dass statische Instanzen nicht GC-geprüft werden, bevor der Anwendungspool recycelt wird, und daher alles, worauf die statische Instanz verweist, nicht GC-geprüft wird. Dies kann zu Problemen bei der Speichernutzung führen.

Wenn Sie eine Instanz mit der gleichen Lebensdauer wie eine Anfrage benötigen, würde ich empfehlen, die HttpContext.Current.ItemsSammlung zu verwenden. Dies ist beabsichtigt, um Dinge zu speichern, die Sie während der Anfrage benötigen. Für ein besseres Design und eine bessere Lesbarkeit können Sie das Singleton-Muster verwenden, um diese Elemente zu verwalten. Erstellen Sie einfach eine Singleton-Klasse, in der die Instanz gespeichert ist HttpContext.Current.Items. (In meiner allgemeinen Bibliothek für ASP.NET habe ich zu diesem Zweck eine generische SingletonRequest-Klasse).

driis
quelle
3
Könnten Sie ein Beispiel für Ihr Singleton-Muster bereitstellen HttpContext.Current.Items?
Airn5475
Weitere Details zu meiner Situation: In meiner Web-App durchläuft der Benutzer eine Klassenbibliothek mit Code, die eine gemeinsam genutzte Klasseneigenschaft verwendet. Ich möchte, dass diese Eigenschaft benutzerspezifisch ist, aber ich möchte diese Eigenschaft nicht an die verschiedenen Funktionen weitergeben müssen. Kann das von Ihnen erwähnte Design richtig damit umgehen?
Airn5475
Könnten Sie bitte die SingletonRequest-Klasse teilen?
Tebo
Ich speichere keine Daten in statischen Klassen. Ich verwende die statische Klasse nur zum Abrufen von Daten oder zum Festlegen von Daten als Datenschicht. Gibt es also ein Problem?
grell
"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"- Gibt es eine Quelle dafür, weil es keinen Sinn ergibt und im Widerspruch zu dem steht, was ich an anderer Stelle gelesen habe. Wenn der AppPool recycelt wird, wird die zugehörige App-Domäne vollständig abgerissen und GC-fähig. In diesem Fall werden alle zugehörigen statischen Instanzen ebenfalls einer GC unterzogen, da ihr Stammverzeichnis (die AppDomain) nicht mehr vorhanden ist. Im Rahmen des Pool-Recyclings wird eine neue AppDomain erstellt und die zugehörigen statischen Instanzen initialisiert.
Nick
30

Statische Mitglieder haben nur einen Bereich des aktuellen Arbeitsprozesses, daher hat dies nichts mit Anforderungen zu tun, da unterschiedliche Anforderungen möglicherweise von demselben Arbeitsprozess verarbeitet werden oder nicht.

  • Verwenden Sie HttpContext.Current.Session, um Daten für einen bestimmten Benutzer und für mehrere Anforderungen freizugeben.
  • Verwenden Sie HttpContext.Current.Items, um Daten innerhalb einer bestimmten Anforderung freizugeben.
  • Um Daten für die gesamte Anwendung gemeinsam zu nutzen, schreiben Sie entweder einen Mechanismus dafür oder konfigurieren Sie IIS so, dass es mit einem einzelnen Prozess arbeitet und eine Singleton / Use-Anwendung schreibt.

Übrigens ist die Standardanzahl der Arbeitsprozesse 1, weshalb das Web voll von Leuten ist, die denken, dass statische Mitglieder einen Bereich der gesamten Anwendung haben.

Moshe Bixenshpaner
quelle
11

Da die Typen in einer App-Domäne enthalten sind, würde ich erwarten, dass statische Klassen vorhanden sind, solange die App-Domäne nicht recycelt wird oder wenn die Anforderung von einer anderen App-Domäne bedient wird.

Ich kann mir verschiedene Möglichkeiten vorstellen, um Objekte für eine bestimmte Anforderung spezifisch zu machen. Dies hängt davon ab, was Sie tun möchten. Beispielsweise können Sie das Objekt in Application.BeginRequest instanziieren und dann im HttpRequest-Objekt speichern, damit alle Objekte in darauf zugreifen können die Anforderungsverarbeitungspipeline.

Sijin
quelle
4

Wenn sie nicht für jede Anfrage eindeutig sind, gibt es eine Möglichkeit, dies zuzulassen?

Nee. Statische Mitglieder gehören dem ASP.NET-Prozess und werden von allen Benutzern der Web-App gemeinsam genutzt. Sie müssen sich anderen Sitzungsverwaltungstechniken wie Sitzungsvariablen zuwenden.

rp.
quelle
1

Normalerweise sind statische Methoden, Eigenschaften und Klassen bei der Application Ebene üblich. Solange die Anwendung gültig ist, werden sie gemeinsam genutzt.

Sie können ein anderes Verhalten angeben, indem Sie das ThreadStaticAttribut verwenden. In diesem Fall sind sie spezifisch für den aktuellen Thread, der meiner Meinung nach für jede Anfrage spezifisch ist.
Ich würde dies jedoch nicht empfehlen, da es zu kompliziert erscheint.

Sie können verwenden HttpContext.Current.Items, um Dinge für eine Anfrage einzurichten, oderHttpContext.Current.Session einzurichten um Dinge für einen Benutzer einzurichten (über Anfragen hinweg).

Im Allgemeinen ist es jedoch Server.Transferam besten, Dinge einmal zu erstellen und sie dann explizit per Methodenaufruf zu übergeben , es sei denn, Sie müssen Dinge wie verwenden .

Sklivvz
quelle
3
Jon Skeet zeigt uns, dass ThreadStatic in ASP.Net stackoverflow.com/questions/4791208/…
Mark Lindell
Abgestimmt, da ein Thread nicht nur für eine Anfrage gilt. Bitte entfernen Sie diese Antwort
siehe Keks