2013-04-08 29 views
0

我與vb.net下面的代碼:.NET內存泄漏,使用GC.Collet()或者不

Public Async Function WriteData(buffer() As Byte, offset As Integer, count As Integer) As System.Threading.Tasks.Task 
     Try 
      Using data_writer = IO.WindowsRuntimeStreamExtensions.AsStreamForWrite(_outputStream) 
       Await data_writer.WriteAsync(buffer, offset, count) 
       Await data_writer.FlushAsync 
      End Using 
     Catch ex As Exception 
      Logger.Write(ex) 
     End Try 
    End Function 

我調用該函數WriteDate太多,但我注意到在增加內存每次我調用函數,因爲您可以看到datawriter流和_outputStream被處置,因爲使用Using。

當我運行vs Profiler時,分析器顯示95%的內存被我的代碼中的「buffer」字節數組保留過多。

1-您是否在我的代碼中看到任何問題? 2-如何清除字節數組?

- 我下面的代碼添加到該函數的行等待data_writer.FlushAsync

buffer = Nothing 
GC.Collect() 

所以我的記憶不會像以前那樣增加後,但我打電話寫數據太多我的應用程序,和我請閱讀,建議不要調用GC.Collect太多。

不調用GC.Collect,內存跳轉到300 MB,GC.Collect()內存不超過50MB。

請指教。

謝謝

回答

2

這是一個通用的GC問題,並非針對Phone或Await。儘管它肯定無助於解決問題。問題是你的緩衝區太大,超過85KB。太大以至於很容易被GC壓縮,因此它被分配到大對象堆中。現在第0代中沒有足夠的小對象來觸發集合。 LOH只在gen#2集合中被清除,因此調用GC.Collect()確實是一種解決方法。

避免必須調用Collect()的兩個基本策略。首先強烈支持使用更小的緩衝區,小到足以在#0中分配。做一點工作總是更好,等待關鍵字應該確實有助於在代碼中做出微小的改變。很難說,我們看不到來電者。

第二個策略是重用緩衝區,所以你只需要其中的一個。這又是多麼容易取決於呼叫者的樣子。

+0

許多感謝@Hans,真是一個非常好的解決方案。 1-分裂緩衝區小於85K可能會降低性能和速度2-我如何重新使用緩衝區? – Sameh 2013-04-08 11:45:07

+0

不,不存在由於小緩衝區I/O會明顯減慢的情況。除非你使緩衝區小於一千字節。注意過早優化,特別是在手機上。一個好的緩衝區大小是4096字節。我無法幫助您弄清楚如何重用緩衝區,我看不到調用此方法的代碼。 – 2013-04-08 11:59:08

+0

非常感謝@Hans你的回答是公平的,謝謝你的時間。 – Sameh 2013-04-08 12:06:17

2

您應該在嘗試控制GC之前瞭解GC的工作方式。垃圾收集主要由「內存壓力」驅動也就是說,當你的程序缺乏即時使用的內存時,爲了釋放一些內容,將會發生一個集合。

不調用GC.Collect,您的內存使用量爲300MB的原因是因爲.NET在運行代碼時沒有承受壓力。因爲它沒有壓力,所以它不會浪費時間來運行一個集合。 300MB的分配內存沒有被主動使用 - 只是因爲你打電話給Collect,你的代碼並不是神奇的效率 - 但是沒有理由在這一點上進行整理。

我的建議是:不要撥GC.Collect,除非你有一個特定的和有意義的理由來減少你的應用程序的內存使用。當需要時,垃圾收集器將自己收集該內存(您可能會看到您的使用量增加,然後定期回落至〜50MB)。

+1

謝謝,但有一段時間我的應用程序關閉,因爲內存達到300 MB,在WP8項目上工作,並且存在內存限制。甚至分析器都會警告我關於內存中保留的字節。 – Sameh 2013-04-08 11:02:41

+1

在你的問題中提到這可能是有用的:-) – 2013-04-08 11:22:35

+0

我很抱歉@丹Puzey忘記提及。 – Sameh 2013-04-08 11:41:57

0

我有同樣的問題,在其他情況下,與HTTP服務器,但我找到了真正的解決方案:

不要從不使用AsStreamForWrite(),直接使用WinPRT IOuputStream(我想這是可能的,即使在VB) AsStreamForWrite()創建一個內部流,它只是吃了內存(在幾種情況下)並且從不釋放它。

+0

親愛的@Poppyto,你有沒有AsStreamForWrite的問題的證明,或者它是爲了你自己的經驗? – Sameh 2014-08-28 08:17:33

+1

驗證是經驗:我花了72小時處理大內存泄漏(本地Web服務器「代理」文件),當我刪除AsStreamForWrite並直接使用WinPRT對象時,我沒有更多內存泄漏。我知道這不是我的錯,因爲內存分析器證實它不是.NET內存問題(所以本機內存問題!),所以忘記GC.Collect和其他。 – Poppyto 2014-08-28 12:22:34