2015-10-14 59 views
1

我使用binaryformatter序列化一個類並使用deflatestream壓縮數據。保存功能如下,並從後臺工作人員調用:序列化背景數據中的數據 - 內存不足異常

public static void save(System system, String filePath) 
{ 
    //Make filestream 
    FileStream fs = new FileStream(filePath, FileMode.Create); 
    try 
    { 
     //Serialize offerte 
     BinaryFormatter bf = new BinaryFormatter(); 
     DeflateStream cs = new DeflateStream(fs, CompressionMode.Compress); 

     bf.Serialize(cs, system); 

     //Push through 
     fs.Flush(); 
     cs.Flush(); 
     cs.Close(); 
    } 
    catch (Exception e) 
    { 
     var mess = e.Message; 
    } 
    finally 
    { 
     //Close 
     fs.Close(); 
    } 
} 

該類有一些「用戶」。有100個用戶需要10秒,文件是2MB。如果有1000個用戶,它會發生內存不足的異常(估計大小爲16MB)。任何人都可以在這裏看到問題,或給出建議如何解決這個問題? (我第一次想到在後臺線程上造成這種情況需要很長時間,但我有其他後臺線程可以運行更長時間。)

+2

'系統'是類型名稱的可怕選擇。 – Amit

+0

你確定你沒有得到任何異常?你正在吞嚥任何發生的事情,這可能會使問題難以追查。 – Paddy

+0

你爲什麼吞嚥異常? –

回答

4

您不會處置您的流,它可能是部分的問題,建議:

public static void save(System system, String filePath) 
{ 
    //Make filestream 
    using(FileStream fs = new FileStream(filePath, FileMode.Create))  
    { 
     //Serialize offerte 
     BinaryFormatter bf = new BinaryFormatter(); 

     using (DeflateStream cs = new DeflateStream(fs, CompressionMode.Compress)) { 

      bf.Serialize(cs, system); 

      //Push through 
      fs.Flush(); 
      cs.Flush(); 
      cs.Close(); 
     } 
    }  
} 

這也可以消除你的異常吞嚥,這可能是一件好事。

+0

看來,這會產生一個不錯的文件。你能向我解釋爲什麼使用using {}語句不會產生內存不足的異常嗎? – Sliver2009

+1

您的兩個流都實現了IDisposable - 對於這樣的類,建議您始終在使用後處理它們,因爲它們可能具有需要發佈的非託管資源。當你有大量的用戶時,這種「整理」可能會對你有所幫助。 – Paddy

+1

在這裏更深入更好的解釋:https://msdn.microsoft.com/en-GB/library/yh598w02.aspx – Paddy

1

您使用實現了System.IDisposable

如果設計師實現了IDisposable他告訴你,他可能使用稀缺資源類的多個對象。在垃圾回收器收集垃圾之前,您可能會擺脫資源。

換句話說:每當您使用實現System.IDisposable的類時,只要您不再需要該類,就應該調用Dispose()。如果您需要該類的其他資源,這尤其需要。

您使用兩個Stream類:FileStream和DeflateStream。他們都實現了IDisposable。如果你不調用Dispose(),垃圾收集器最終會,但同時這些Streams使用的資源不可用於任何其他人。

最簡單的方法,以確保設置在一次性對象是使用using語句:

using (var myStream = new FileStream(...)) 
{ 
    ... // use myStream 
} 

當到達右括號,myStream.Dispose()被調用,有效地釋放所有稀缺它使用的資源。

這適用於每個用於離開{...}塊的方法,包括break,return甚至Exceptions。

因此使用是一種非常安全的方法:Dispose()將始終被調用。順便說一下:Dispose()也會注意到Streams被刷新和關閉,所以在using語句結束時,你不需要Flush()和Close()。