2012-02-24 29 views
1

我正在使用ASP.NET 4.0。如何通過配置靜態方法來防止故障(內存泄漏)?

從過去幾周來,很少有用戶抱怨應用程序開始出現故障。 GridView突然開始顯示同一用戶或另一個併發用戶在當天的任何時間點可能訪問的DropDown控件的內容。同樣,DropDown控件可能會被任何舊結果集的RowID填充,而不是實際的項目。

我遇到了一篇文章:Users seeing other users data in ASP.NET作者討論了關於負責內存泄漏行爲的靜態對象。

它讓我想起了我的項目中的一個類,它是Static並且包含public static方法。此類包含填充DropDown,爲查詢輸入返回DataSet或基於查詢輸入返回標量對象的方法。

提取這個類的低於:

public static class reuse 
{ 
    public static void FillDropDownList(string Query, DropDownList DropDownName, string ConnectionStringParameter) 
    { 
     SqlDataReader dr; 

     try 
     { 
      dbConnection.OpenConnection(ConnectionStringParameter); 

      //Check whether the Drop Down has existing items. If YES, empty it. 
      if (DropDownName.Items.Count > 0) 
       DropDownName.Items.Clear(); 

      SqlCommand cmd = new SqlCommand(Query,dbConnection.cn); 
      dr = cmd.ExecuteReader(); 

      DropDownName.Items.Add("-- Select --"); 
      DropDownName.Items.Add("All"); 
      while (dr.Read()) 
       DropDownName.Items.Add(dr[0].ToString()); 

      dr.Close(); 
     } 
     catch (Exception ex) 
     { 
      rpkCustomErrorHandler.GetScript(HttpContext.Current.Response,ex.Message.ToString()); 
     } 
     dbConnection.CloseConnection(); 
    } 
} 

我想知道這是否是我上面所討論的故障原因。如果是,那麼在方法的任務完成之後是否有辦法處理靜態方法。我是否需要將該類從Static更改爲默認普通類?

編輯

我有另一類這也是靜態的,用於通過上述類:

public static class dbConnection 
{ 
    public static SqlConnection cn = new SqlConnection(); 

    public static void OpenConnection() 
    { 
     try 
     { 
      cn.ConnectionString = ConfigurationManager.ConnectionStrings["cnWebTwDrill"].ToString(); 

      if (cn.State == ConnectionState.Closed) 
       cn.Open(); 
     } 
     catch (Exception) 
     { 
      throw;    
     } 
    } 
} 

要我請從連接類「靜態」和使調用這個類每次使用一個獨特的實例?

+0

你的下拉是在GridView中?你能提供一些相關的aspx代碼嗎? – 2012-02-24 06:01:47

+0

No DropDown不在GridView中,但是無論何時我需要填充DropDown或GridView,我都會調用此類,如下所示:reuse.FillDropDownList(「Select CustomersNames From Customer,ComboBox1); – RKh 2012-02-24 06:06:41

+0

我剛剛意識到GridViews已填充通過SQL DataSource,每個GridView都是唯一的 – RKh 2012-02-24 06:07:59

回答

3

您向我們展示的代碼是靜態類/方法使用不當的示例。你把一個靜態方法或類放入一個簡單的東西,以適應一個對象和哪些不需要狀態。

您在那裏的功能應該在將數據分配給服務器控件的業務層(將檢索數據)和UI /控制器(在本例中爲Page)之間分開。所有這些操作都是特定於請求的,因此沒有理由使用靜態方法。這只是程序性編程的一個標誌。當處理數據庫訪問(或一次性對象)時,應該使用使用語句。這樣

using(var conex=GetConnection()) 
{ 
    try 
    { 
    conex.Open(); 
    //do stuff 

    var cmd= new SqlCommand();//cfg command 
    using (var rd= cmd.ExecuteReader()) 
     { 
      //do read 
     } 
    } 
    catch(Exception ex) 
    { 
     //handle exception 
    } 
} 
使用聲明

東西在塊結束時自動調用Dispose。它基本上

try {} 
finally{ //dispose }. 
+0

完全同意這是一個糟糕的設計。實際上,這個課程在很少的獨立應用程序中使用,並且附加到這個在線應用程序中的同一個人,我需要處理這些應用程序。這個類可以直接處理併發連接而不出現故障? – RKh 2012-02-24 08:11:15

+0

我已經告訴過你了。爲了以最快的方式移動Page_Load事件處理程序中的功能,至少它會使用請求數據,但它仍然是錯誤的編碼。當處理併發時,static是最糟糕的方式,如果你必須使用static,那麼你需要線程鎖定http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx。 – MikeSW 2012-02-24 08:21:23

+0

查看我更新的帖子。 – RKh 2012-02-24 09:01:32

1

它不是一個泄漏或處理其狀態靜態對象的問題。這個函數是靜態的,但它不是statefull操作的所有上下文都存在於調用中,因爲此類中所有不是參數的對象都將自動清除。但是,如果您定義某種類型的靜態數據,則同一應用程序域中的任何用戶都將共享該值。這就是說,每當你使用靜力學時,你都必須小心謹慎,因爲它們很難測試替換,並且在多線程情況下非常困難。

+0

如果我使用GC .Collect()每次登錄清償可能已被保留在內存中,而不是設置? – RKh 2012-02-24 06:14:20

+0

它不是關於處置。GC收集永遠不會刪除他們總是可達靜態對象有不符合垃圾收集的任何資源後的只有當它們離開時,應用程序域纔會消失。 – rerun 2012-02-24 06:37:21

+0

如何處置靜態對象? – RKh 2012-02-24 07:12:02

1

快捷我懷疑你所看到的錯誤是由內存泄漏或故障處置靜態物體引起的。

但是,要回答您的問題:釋放靜態對象的內存的唯一方法是將關聯的靜態引用設置爲null。之後,他們將無法到達,GC將負責處理剩下的事情。

兩件事情,可能有助於實際問題:

  1. 故障緩存策略可能會導致無意的數據共享(HTTP級別或與ASP.NET對象緩存,輸出緩存等)
  2. 一定要在所有對可以在線程之間共享的靜態對象的引用中使用鎖定,其中一個線程可能會在另一個線程正在讀取對象時寫入該對象。

順便說一句,OP中的靜態方法似乎沒有使用任何靜態對象;它所觸及的一切似乎都是作爲一個論點來傳遞的。靜態方法本身不分配或保存內存引用。

更新:

想要共享頁面請求之間的單一數據庫連接是一個錯誤,而且幾乎肯定會導致不確定的行爲(例如,一個頁面可以發出一個查詢,而另一個頁面讀取響應)。數據庫連接已被運行時池化;你不需要自己優化那部分。每個頁面請求不應該只使用一個新的SqlConnection,也應該叫事後連接對象上Dispose(),及時釋放回池中。

+0

我根本沒有使用緩存。如何鎖定靜態對象?我也注意到當一個GridView被SQL DataSource刷新時出現錯誤。在這種情況下,我不會調用上述靜態類。我擔心我有一個類似於上面的Static Connection類。 – RKh 2012-02-24 08:55:02

+0

查看我上面更新的帖子。 – RKh 2012-02-24 08:59:49

+0

查看我更新的答案。 – RickNZ 2012-02-24 10:00:16