2013-02-22 125 views
7

我有一些讀取文件的對象,將數據保存在數組中並進行一些操作。序列是創建對象A,使用對象A操作。創建對象B,使用對象B操作... 每個對象讀取的數據可能大約爲10 MB。所以最好的選擇是在每個對象操作後刪除每個對象。讓說,我想我的計劃分配大約10 MB內存,10MB不是* 1000個=對象1GB需要刪除對象:實現在函數中處理或創建對象?

的對象是這樣的:

class MyClass 
{ 
    List<string[]> data; 

    public MyClass(string datafile) 
    { 
     using (CsvReader csv = new CsvReader(new StreamReader(datafile), true)) 
     { 
      data = csv.ToList<string[]>(); 
     } 
    } 

    public List<string> Operate() 
    { 
    ... 
    } 

} 

我的問題是:我應該執行處置?而這樣做:

List<string> results = new List<results>(); 

using (MyClass m = new MyClass("fileM.txt")) 
      { 
       results.AddRange(m.Operate()); 
      } 

using (MyClass d = new MyClass("fileD.txt")) 
      { 
       results.AddRange(d.Operate()); 
      } 

... 

從來就讀,實施一次性的,當您使用unmmanaged資源(套接字,流,...)的建議,但在我的課,我只有大數據陣列。

另一種方式是爲每個對象創建函數(我想GC將刪除的功能自動創建一個對象):

List<string> results = new List<results>(); 
results.AddRange(myFunction("fileM.txt")); 
results.AddRange(myFunction("fileD.txt")); 


public List<string> myFunction(string file) 
{ 
MyClass c = new MyClass(file); 
return results.AddRange(c.Operate()); 
} 
+0

我編輯了你的標題。請參見「[應的問題包括‘標籤’,在他們的頭銜?(http://meta.stackexchange.com/questions/19190/)」,這裏的共識是「不,他們不應該」。 – 2013-02-22 02:04:00

回答

5

IDisposable等不會幫助你在這裏,因爲它不會引起任何要收集的東西。在這種情況下,最好的方法是使用來減少分配 - 實質上成爲您自己的內存管理器。例如,如果您的List<string>很大,您可以通過重新使用列表來避免很多陣列 - 顯然在清除它們之後。如果您撥打.Clear(),支持數組不會重置 - 它只是設置一個邏輯標記以將其視爲空。在你的具體情況下,你的很多對象將成爲個人string s;這是棘手的,但至少它們很小,應該可以在零代收集。

+1

如果你想調整後備數組的大小,你可以在調用Clear()後設置'Capacity = someValue'。 (請注意,它不會允許您將「容量」降低到當前大小以下,因此您必須先清除它。) – porges 2013-02-22 02:12:26

+0

重複使用列表是一個不錯的主意,但在我的情況下很複雜。我從一些CSV文件中讀取數據。對於每個csv,我提取數據列(每列的字符串列表)並創建一些圖。重新使用每個csv讀取數據的列表很容易實現。但是,重新列出每個csv的列是更復雜的。一個csv可能有3列(3列表),antoher 8列(8列表),所以我必須創建儘可能多的列表作爲csv可能具有的最大列數。然後爲每個列重新列出每個列表..一個複雜的代碼。用colums刪除每個對象會更容易:) – Alberto 2013-02-28 12:53:51

3

在你的情況下,我會分配一個緩衝區數組。例如,分配一個10 MB的陣列一次,並填充所需的數據。然後,當你到達下一個對象時,只需重新使用該數組。如果你需要更大的數組,你可以分配一個新的,更大的數組,然後使用它。垃圾收集器將最終刪除您的較小的一個。

你也可以使用一個List<T>,它會在內部做相同的事情(分配一個數組,保持它,直到它變得太小,分配一個新的)。只需Clear它在創建下一個對象之前。

請注意,您不能強迫 垃圾收集器收集的對象。 IDisposable實際上只用於清理非託管資源,因爲垃圾收集器不知道它們,或者關閉(文件)句柄。調用Dispose不保證(或暗示)該對象已從內存中移除。

但是,如果你什麼也沒有改變,你的代碼仍然是正確的,並且正常工作。垃圾收集器負責刪除未使用的對象,只要感覺這樣做,它就會確保在任何時候都有足夠的可用內存。讓收藏者完成工作的唯一方法是放棄對舊對象的引用(通過覆蓋它們或將其設​​置爲null,或讓它們超出範圍)。

)您可以強制垃圾收集器通過調用GC.Collect()來收集數據。但是,建議使用而不是。讓垃圾收集器自己弄清楚。

0

如果您使用.NET 4.0或更高版本,請查看BlockingCollection類。 constructor that takes the Int32 parameter允許您指定集合大小的上限。方法AddTake作爲節流閥工作。如果尚未達到上限,則添加將成功。如果有,它會阻止。只有當物品存在時,Take纔會成功。如果沒有項目存在,它將阻塞,直到有一個可用。當然,這個類有這些方法的一些變體,所以要全面檢查文檔以查看哪些(如果有的話)是有意義的。