2012-01-18 114 views
52

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

protected static int SomeGlobalUnsecureID; 
protected static string SomeGlobalUnsecureString; 

並定義PageLoad事件中的變量。例如,我從數據庫中檢查ID,如果它與SomeGlobalUnsecureID不同,我從其他地方更新SomeGlobalUnsecureID和String,否則保持原樣。這在我的應用中非常安全。邏輯(即那些數據不安全,每個人都可以訪問它們,沒問題);只是我要完成的事情是

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

  2. 變化當且僅當持續的信息是從一個在 「記憶」不同(因爲實際閱讀該字符串是耗時 我。

現在,因爲我使pageLoad的檢查,我在重新加載網頁沒有問題。但是我的頁面充滿的WebMethods,有時我看到塔t靜態變量歸零。而奇怪的部分是;即使靜態變量歸零(所以 - >無服務器或應用程序池重啓等),會話仍處於活動狀態。

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

+1

您問題頂部的聲明是* not * static,順便說一句。 – 2012-01-18 23:35:36

+1

:)好的,更正 – 2012-01-18 23:45:55

+1

'在PageLoad事件中定義變量'。我想你的意思是初始化?定義一個變量就是你在編寫'protected static int Something;' – 2013-02-13 22:59:05

回答

73

靜態變量在應用程序域的生命週期中持續存在。因此,導致靜態變量「重置」的兩件事是重新啓動應用程序域或使用新類。對於存儲在aspx Page類中的靜態變量,如果ASP.NET決定將aspx Page重新編譯爲新類,並用新的類替換舊頁面類,則可能會丟失靜態變量。

出於這些原因,如果系統決定重新啓動或更換類(.NET doesn't kill or unload classes/assemblies in a running app domain那麼因爲你正在與重啓或更換一個新的類的靜態變量將復位。這適用於ASPX頁面和classes in the App_Code folder

如果ASP.NET由於任何原因認爲需要重新編譯它(see ASP.NET dynamic compilation,

),您將無法防止應用程序域重新啓動時丟失靜態變量,但您可以嘗試避免從類替換。你可以把你的靜態變量放在一個不是aspx頁面的類中,它不在App_Code目錄中可能希望將它們放置在您的程序中的某個static class上。

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

靜態變量是每個池,這意味着如果你有2個池運行你的asp.net站點,你有2個不同的靜態變量。 (Web garden mode

如果系統以這種方式之一重新啓動您的asp.net應用程序,靜態變量會丟失。

  1. 池決定需要重新編譯。
  2. 您打開app_offline.htm文件
  3. 你讓池
  4. 池是達到您已經定義並重新啓動一些限制的手動重啓。
  5. 由於任何原因您重新啓動iis或池。

這個靜態變量不是線程安全的,你需要使用關鍵字特殊,如果你從不同的線程訪問它們。

由於應用程序重新啓動將重置靜態,無論如何,如果您確實想要保存數據,則應該使用自定義類將數據存儲在數據庫中。您可以使用database session state mode將每個用戶的信息存儲在Session State中。 ASP.NET應用程序狀態/變量不會幫助您,因爲they are stored in memory, not the database,所以它們在應用程序域重新啓動時也會丟失。

+0

什麼是更好的方法來存儲這樣的持久化應用程序數據,某種外部緩存存儲? – 2012-01-19 00:16:41

+0

@DanielPowell Depend。在我的程序中,我有許多池和許多線程,這些線程是數據庫中保存的所有線程數據的共同點。將每個應用程序的常用數據保存到全局靜態類。 – Aristos 2012-01-19 00:21:37

+0

最後一件事;我創建了一個名爲global的靜態類,並在其中添加了屬性。在.cs代碼中工作正常,但在aspx中,我無法使用<%= global.someproperty%>訪問全局類,儘管它們在相同的命名空間中。這是正常的嗎? – 2012-01-19 00:37:35

-5

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

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

Down vote,this answer is not related to the question。 (OP清楚地理解靜態變量應該如何工作 - 問題是爲什麼它們不能正確工作) - 另外,解釋措辭不佳。 – BrainSlugs83 2016-02-02 20:40:27

4

我認爲以下兩點也是靜態變量的生命週期很重要:

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

2 - 在您的應用程序池的高級設置中,選中「Process Model」 - >「Idle Time-out(minutes)」設置。它的默認值是20,這意味着在應用程序池中每20分鐘不活動,工作進程將被終止/掛起,這將導致您的靜態變量丟失。此設置用於在某個時間段內未使用應用程序池時釋放資源。您可以將其設置爲0以禁用超時。

+0

謝謝。 **回收**是我遇到的問題。 – Isaac 2017-10-07 07:58:12