簡體   English   中英

ASP.NET靜態變量的生命周期

[英]Lifetime of ASP.NET Static Variable

我在頁面類(而不是Global.asax)中定義的靜態變量中保存一些信息。 我只在代碼中聲明變量,例如:

protected static int SomeGlobalUnsecureID;
protected static string SomeGlobalUnsecureString;

並在PageLoad事件中定義變量。 例如,我從數據庫中檢查ID,如果它與SomeGlobalUnsecureID不同,則從其他位置更新SomeGlobalUnsecureID和String,否則保持不變。 這在我的應用程序中絕對安全。 邏輯(即那些數據不安全,每個人都可以訪問它們,沒問題); 我唯一想完成的是

  1. 無論連接的用戶如何,都保持相同的內存量

  2. 僅當持久性信息與“內存”中的信息不同時才進行更改(因為實際讀取字符串對我來說很耗時。

現在,由於我在PageLoad中進行了檢查,因此重新加載的頁面沒有問題。 但是,我的頁面上充滿了WebMethods,有時我看到靜態變量被清零。 而奇怪的是: 即使靜態變量為零,會話仍處於活動狀態(因此->沒有服務器或應用程序池重啟等)

這對我來說真的很奇怪。 我假設靜態變量將保持其值,直到應用程序(以某種方式)結束。 但是,即使會話未過期,靜態變量也將清零。 你有什么建議? 使用應用程序變量是更好的選擇嗎? 我在網上閱讀的所有文檔都建議使用靜態變量而不是應用程序變量,是否需要以某種方式聲明它們?

靜態變量在應用程序域的生命周期內一直存在。 因此,導致您的靜態變量“重置”的兩件事是應用程序域重啟或使用新類。 對於將靜態變量存儲在aspx Page類中的情況,當ASP.NET決定將aspx Page重新編譯為新類時,您可能會丟失靜態變量,而用新的類替換舊的頁面類。

由於這些原因,如果系統決定重新啟動或替換該類( .NET不會殺死正在運行的應用程序域中的類/程序集 ),則您的靜態變量將重置,因為您將通過重新啟動或替換獲得一個新的類。 這適用於aspx頁面和App_Code文件夾中的類

如果出於任何原因認為需要重新編譯該類,則ASP.NET將替換該類( 請參見ASP.NET動態編譯 )。

您無法防止由於應用程序域重啟而丟失靜態變量,但是您可以嘗試避免在類替換中使用它。 您可以將靜態變量放在不是aspx頁面且不在App_Code目錄中的類中。 您可能希望將它們放在程序中某個static class

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

靜態變量是每個池的,這意味着如果您有2個運行asp.net站點的池,則您將有2個不同的靜態變量。 網絡花園模式

如果系統使用這種方式之一重新啟動asp.net應用程序,則靜態變量將丟失。

  1. 池決定需要重新編譯。
  2. 您打開app_offline.htm文件
  3. 您手動重新啟動池
  4. 池已達到您定義的一些限制,然后重新啟動。
  5. 出於任何原因,您都將重新啟動iis或池。

此靜態變量不是線程安全的,如果您從其他線程訪問它們,則需要使用特殊的lock關鍵字。

由於應用程序重啟無論如何都將重置您的靜態信息,因此,如果您確實要保留數據,則應使用自定義類將數據存儲在數據庫中。 您可以存儲每個用戶的信息會話狀態數據庫會話狀態模式 ASP.NET應用程序狀態/變量將無法為您提供幫助,因為它們存儲在內存中,而不是數據庫中 ,因此它們也會在應用程序域重新啟動時丟失。

我認為以下兩點對於靜態變量的生命周期也很重要:

1-在應用程序池的高級設置中,選中“回收”->“常規時間間隔(分鍾)”設置。 它的默認值為1740,這意味着每29小時您的靜態變量會由於應用程序池的回收而丟失。 此設置用於終止可能的內存泄漏。 我不會更改此設置。

2-在應用程序池的高級設置中,檢查“過程模型”->“空閑超時(分鍾)”設置。 默認值為20,這意味着在應用程序池中每20分鍾不活動時,工作進程將被終止/掛起,這將導致您的靜態變量丟失。 當一段時間未使用應用程序池時,此設置用於釋放資源。 您可以將其設置為0以禁用超時。

靜態變量用於存儲所有具有相同值的對象

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM