2012-10-19 80 views
3

以下代碼在〜200次調用後崩潰。我在每次調用GC之後都嘗試過GC,並且在另一個GC上使用了MemoryWarning塊,但它仍然崩潰。內存泄漏/崩潰轉換圖像數據

public byte[] ConvertImage(string base64String) 
{ 
    try 
    { 
     byte[] encodedDataAsBytes = Convert.FromBase64String (base64String); 
     base64String = ""; 
     NSData data = UIImage.LoadFromData (NSData.FromArray (encodedDataAsBytes)).AsPNG(); 
     encodedDataAsBytes = null; 
     Byte[] returnBytes2 = new Byte[data.Length]; 
     System.Runtime.InteropServices.Marshal.Copy 
     (data.Bytes, returnBytes2, 0, System.Convert.ToInt32(data.Length)); 
     data.Dispose(); 
     return returnBytes2; 
    } 
    catch(Exception ex) 
    { 
     Log.LogError("ConvertImage", ex); 
     return null; 
    } 
} 

TIA, 裏克

多撞頭和精湛的幫助下從Xamarin支持後 - 答案是包裹方法using (var pool = new NSAutoreleasePool())

一切都好吧!哦,還有一點,將.PNG改爲.JPEG也會減輕負載。

回答

3

這是相當內存密集型。 base64 stringbyte[]陣列,NSData,UIImage,第二個NSData,第二個byte[]陣列。這是您正在處理的圖像所需內存的許多倍。

根據代碼的調用方式(例如,對一堆圖像進行循環),您可能會比GC更快地分配內存。在某些時候,iOS會觸發一個內存警告(但這對循環無用),如果內存使用率沒有迅速降低,它會殺了你。

您可以通過處理代碼創建的每個IDisposable實例輕鬆地降低內存要求。現在你只處理你創建的兩個NSData實例中的一個,並且你沒有處置UIImage。你可以這樣處置它們全部:

byte[] encodedDataAsBytes = Convert.FromBase64String (base64String); 
using (var nsd1 = NSData.FromArray (encodedDataAsBytes)) 
using (var img = UIImage.LoadFromData (nsd1)) 
using (NSData data = img.AsPNG()) { 
    byte[] returnBytes2 = new byte [data.Length]; 
    Marshal.Copy (data.Bytes, returnBytes2, 0, (int) data.Length); 
    return returnBytes2; 
} 

接下來,代碼稍後的目的是什麼?即你在做什麼byte[]包含PNG圖像?這本身並不是很有用,但如果你只是將它保存到磁盤上,那麼你可以從NSData這樣做,並跳過最後的byte[]分配。

也可以使用其他技巧,依賴於使用情況(例如,如果可能,重新使用第二個byte[]緩衝區),但我們需要更多地瞭解代碼的使用方式。

+0

仍然崩潰。實際上通過的記錄比我原來的代碼少。調用該例程以從來自桌面應用程序的XML文件轉換base64編碼的圖像數據。 – Rick

+0

您可能希望以二進制而非base64字符串傳輸(以跳過一個步驟)。 OTOH你**更好**在做設計更改之前(在顯而易見的Dispose調用旁邊)測量。嘗試使用Apple的樂器來查看內存分配的位置和時間,以及如何避免它(或減少內存需要的時間)。一旦你有數字(和關於你的應用程序的更多細節),那麼我們將能夠找到/建議更多的解決方案(即迭代猜測很容易,但通常沒有幫助)。 – poupou

+0

無法更改桌面XML - 現在它已經瘋狂了。我無法讓Instruments工作,在調試模式下,運行Import的線程永遠不會啓動,不知道該怎麼做。 GC爲什麼不在這種情況下工作? – Rick