以下代码在~200次调用后崩溃。我在每次调用后尝试使用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也减轻了负担。
答案 0 :(得分:3)
这是非常耗费内存的。 base64 string
,byte[]
数组,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;
}
接下来,代码的目的是什么?即你在使用包含PNG图像的byte[]
做什么?它本身并不是很有用,但是如果你只是将它保存到磁盘上,那么你可以从NSData
执行此操作并跳过上一次byte[]
分配。
也可以应用依赖于使用的其他技巧(例如,在可能的情况下重用第二个byte[]
缓冲区)但我们需要了解有关代码使用方式的更多信息。