Lebensdauer der statischen ASP.NET-Variablen

78

Ich halte einige Informationen in statischen Variablen, die in der Seitenklasse definiert sind (nicht in Global.asax). Ich deklariere nur Variablen im Code wie:

protected static int SomeGlobalUnsecureID;
protected static string SomeGlobalUnsecureString;

und definieren Sie die Variable im PageLoad-Ereignis. Zum Beispiel überprüfe ich die ID aus der Datenbank. Wenn sie sich von SomeGlobalUnsecureID unterscheidet, aktualisiere ich SomeGlobalUnsecureID und String von einem anderen Ort, ansonsten lasse ich sie unverändert. Dies ist in meiner App absolut sicher. Logik (dh diese Daten sind nicht sicher, jeder kann darauf zugreifen, kein Problem); Das einzige, was ich erreichen möchte, ist

  1. Halten Sie unabhängig von den verbundenen Benutzern dieselbe Speicherkapazität

  2. Ändern Sie dies nur dann, wenn sich die persistenten Informationen von denen im 'Speicher' unterscheiden (da das Lesen der Zeichenfolge für mich zeitaufwändig ist.

Jetzt, da ich in PageLoad einchecke, habe ich keine Probleme beim erneuten Laden von Seiten. Meine Seite ist jedoch voller WebMethods, und manchmal sehe ich, dass die statischen Variablen auf Null gesetzt sind. Und der seltsame Teil ist; Die Sitzung ist auch dann noch aktiv, wenn die statischen Variablen auf Null gesetzt sind (also-> kein Server oder App. Neustart des Pools usw.)

Das ist wirklich seltsam für mich. Ich gehe davon aus, dass die statische Variable ihren Wert behält, bis die Anwendung (irgendwie) endet. Aber auch die Sitzung ist nicht abgelaufen, die statische Variable ist auf Null gesetzt. Was schlagen Sie vor? Ist die Verwendung von Anwendungsvariablen eine bessere Wahl? Alle Dokumente, die ich im Web gelesen habe, schlagen statische Variablen anstelle von Anwendungsvariablen vor. Muss ich sie irgendwie anders deklarieren?

Paul Simmons
quelle
1
Die Erklärungen oben in Ihrer Frage sind übrigens nicht statisch.
Andrew Barber
1
'Definieren Sie die Variable im PageLoad-Ereignis.' Ich denke du meinst initialisieren? Das Definieren einer Variablen ist das, was Sie tun, wenn Sie schreibenprotected static int Something;
Carl G
"Jetzt, da ich PageLoad einchecke, habe ich keine Probleme beim erneuten Laden von Seiten." - Das klingt nach einer Rennbedingung, die darauf wartet, passiert zu werden. Ich würde stattdessen eine thread-sichere verzögerte Initialisierung in Betracht ziehen.
Millimoose
Ein statisches Mädchen hält bis zum nächsten Recycling an. Setzen Sie Ihre Variablen in eine statische Klasse, um sie in anderen zu verwenden
Mbithy Mbithy

Antworten:

106

Statische Variablen bleiben für die Lebensdauer der App-Domäne erhalten. Die beiden Dinge, die dazu führen, dass Ihre statischen Variablen zurückgesetzt werden, sind ein Neustart der App-Domäne oder die Verwendung einer neuen Klasse. In Ihrem Fall mit statischen Variablen, die in einer Aspx-Seitenklasse gespeichert sind, verlieren Sie möglicherweise die statischen Variablen, wenn ASP.NET beschließt, die Aspx-Seite in eine neue Klasse neu zu kompilieren und die alte Seitenklasse durch die neue zu ersetzen.

Aus diesen Gründen werden Ihre statischen Variablen zurückgesetzt, wenn das System beschließt, die Klasse neu zu starten oder zu ersetzen ( .NET beendet oder entlädt keine Klassen / Assemblys in einer laufenden App-Domäne ), da Sie beim Neustart oder Ersetzen eine neue Klasse erhalten. Dies gilt sowohl für aspx-Seiten als auch für Klassen im Ordner App_Code

ASP.NET ersetzt eine Klasse, wenn aus irgendeinem Grund eine Neukompilierung erforderlich ist ( siehe Dynamische ASP.NET-Kompilierung) ).

Sie können den Verlust statischer Variablen bei einem Neustart der App-Domäne nicht verhindern, aber Sie können versuchen, die Klassenersetzung zu vermeiden. Sie können Ihre statischen Variablen in eine Klasse einfügen, die keine Aspx-Seite ist und sich nicht im Verzeichnis App_Code befindet. Vielleicht möchten Sie sie static classirgendwo in Ihrem Programm platzieren.

public static class GlobalVariables
{
    public static int SomeGlobalUnsecureID;
    public  static string SomeGlobalUnsecureString;
}

Die statischen Variablen beziehen sich auf jeden Pool. Wenn Sie also zwei Pools haben, auf denen Ihre asp.net-Site ausgeführt wird, haben Sie zwei verschiedene statische Variablen. ( Webgartenmodus )

Die statischen Variablen gehen verloren, wenn das System Ihre asp.net-Anwendung auf eine dieser Arten neu startet.

  1. Der Pool entscheidet, dass eine Neukompilierung erforderlich ist.
  2. Sie öffnen die Datei app_offline.htm
  3. Sie führen einen manuellen Neustart des Pools durch
  4. Der Pool erreicht einige Grenzen, die Sie definiert haben, und führt einen Neustart durch.
  5. Aus irgendeinem Grund starten Sie das iis oder den Pool neu.

Diese statischen Variablen sind nicht threadsicher, und Sie müssen das Schlüsselwort lock verwenden, insbesondere wenn Sie von verschiedenen Threads aus darauf zugreifen.

Da ein App-Neustart Ihre Statik zurücksetzt, sollten Sie die Daten mithilfe benutzerdefinierter Klassen in einer Datenbank speichern, wenn Sie Ihre Daten wirklich beibehalten möchten. Sie können Informationen pro Benutzer im Sitzungsstatus mit einem Datenbanksitzungsstatusmodus speichern . ASP.NET-Anwendungsstatus / -Variablen helfen Ihnen nicht, da sie im Speicher und nicht in der Datenbank gespeichert sind und daher auch beim Neustart der App-Domäne verloren gehen.

Aristos
quelle
6
@Aristos Dies mag eine alte Frage sein, aber Ihre Antwort ist nicht korrekt. Wenn eine Klassenvariable statisch ist, spielt es keine Rolle, wie viele Instanzen dieser Klasse Sie erstellen und beenden. Diese Variable behält ihren Wert, solange ihre Assembly im Speicher geladen bleibt. Da IIS gehostete Anwendungen regelmäßig recycelt, werden einige Assemblys entladen und dann erneut geladen, was zum Verlust statischer Variablendaten führt. Schauen Sie sich auf diese
Thomas CG de Vilhena
1
@ ThomasC.G.deVilhena Ich sage (stimme zu) dasselbe mit dir? Nicht gut getippt? Können Sie bitte meine Frage bearbeiten und diesen Teil, den Sie sagen, korrigieren?
Aristos
1
Ich denke, das Problem ist, dass die statischen Variablen in einer Aspx-Datei definiert sind (die eine nicht statische Klasse sein muss). Neben einem Neustart der Anwendung (der alle statischen Variablen löscht) kompiliert IIS auch Aspx-Seiten neu (wenn sie geändert werden, oder möglicherweise aus anderen Gründen) und laden Sie dann die neue kompilierte Assembly. Die neu kompilierte aspx-Seite / Klasse ist eine neue Klasse mit eigenen statischen Variablen. Das Umschalten der Variablen auf eine statische Klasse sollte das Zurücksetzen verhindern, außer im Falle eines Neustarts der Anwendung, da jetzt keine Aspx-Neukompilierung für die Klasse erfolgt.
Carl G
1
@ ThomasC.G.deVilhena Wenn Sie einen Teil dieser Antwort ändern möchten, um sie genauer zu machen, tun Sie dies bitte.
Aristos
1
@CarlG Ich schlage Ihnen dasselbe vor, wenn Sie einen Teil dieser Antwort ändern oder andere Aspekte hinzufügen möchten, um sie genauer zu machen, tun Sie dies bitte.
Aristos
21

Ich denke, die folgenden zwei Punkte sind auch wichtig für die Lebensdauer statischer Variablen:

1 - Aktivieren Sie in den erweiterten Einstellungen Ihres Anwendungspools die Einstellung "Recycling" -> "Regelmäßiges Zeitintervall (Minuten)". Der Standardwert ist 1740. Dies bedeutet, dass Ihre statischen Variablen alle 29 Stunden durch das Recycling Ihres Anwendungspools verloren gehen. Diese Einstellung wird zum Beenden möglicher Speicherlecks verwendet. Ich würde diese Einstellung nicht ändern ..

2 - Aktivieren Sie in den erweiterten Einstellungen Ihres Anwendungspools die Einstellung "Prozessmodell" -> "Leerlaufzeitüberschreitung (Minuten)". Der Standardwert ist 20. Dies bedeutet, dass in jeweils 20 Minuten Inaktivität in Ihrem Anwendungspool die Arbeitsprozesse beendet / angehalten werden, wodurch Ihre statischen Variablen verloren gehen. Diese Einstellung wird zum Freigeben von Ressourcen verwendet, wenn der Anwendungspool längere Zeit nicht verwendet wird. Sie können es auf 0 setzen, um das Zeitlimit zu deaktivieren.

sotn
quelle
1
Vielen Dank. Recycling war in meinem Fall das Problem.
Isaac
IMHO sollten die Standardrecyclingeinstellungen für die meisten Anwendungen geändert werden, da sie sich "verschieben" - ich denke, ich möchte genau wissen, wann der Pool recycelt wird, ohne darüber nachdenken zu müssen.
Combatc2
-12

Die statische Variable wird verwendet, um das gesamte Objekt für denselben Wert zu speichern

protected void Page_Load(object sender, EventArgs e)
{
    sss s1, s2;
    s1 = new sss();
    s1.TotalMark = 10;
    s2 = new sss();
    s2.TotalMark = 20;
    sss.SchoolName = "St.Joseph's Hr.Sec.S"; //We can access through class and assign common to all
    s1.PrintData();
    s2.PrintData();
}

public class sss
{
    public static string SchoolName { set; get; }
    public int TotalMark { set; get; }
    public string StudentName{set;get;}
    public void PrintData()
    {
        Console.WriteLine(TotalMark);
        Console.WriteLine(SchoolName);
        Console.WriteLine(StudentName);
    }
}

quelle
3
Diese Antwort hat nichts mit der Frage zu tun. (Das OP versteht klar, wie statische Variablen funktionieren sollen. - Die Frage ist, warum sie nicht richtig funktionieren.) - Außerdem ist die Erklärung schlecht formuliert.
BrainSlugs83