内存泄漏/崩溃转换图像数据

3
以下代码在调用约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,Rick

经过长时间的思考和Xamarin支持团队的帮助,答案就是将该方法封装在using (var pool = new NSAutoreleasePool ())中。

现在一切都很好!哦,还有一个要点,将.PNG更改为.JPEG也可以减少负载。

1个回答

3
这需要相当多的内存。包括base64字符串、byte[]数组、NSData、UIImage、第二个NSData和第二个byte[]数组,它们的总内存远超出您正在处理的图像所需的内存。
根据代码如何被调用(例如循环处理大量图像),您可能会比GC回收内存更快地分配内存。在某些时候,iOS会触发内存警告(但这在循环中没有任何帮助),如果内存使用量没有迅速减少,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[]缓冲区),但我们需要更多关于代码如何被使用的信息。


仍然崩溃。实际上比我的原始代码处理更少的记录。该例程被调用以将来自桌面应用程序的XML文件中的base64编码图像数据转换。 - Rick
你可能想转换为二进制而不是base64字符串(以跳过一步)。另一方面,在进行设计更改之前最好先进行度量(除了显然的“Dispose”调用)。尝试使用苹果的Instruments工具查看内存分配的时间和位置,以及如何避免它(或减少需要内存的时间)。一旦你有了数字和关于应用程序的更多详细信息,那么我们就能够找到/建议更多解决方案(即迭代猜测很容易,但通常没有帮助)。 - poupou
无法更改桌面XML - 它已经在外面了。我无法让Instruments工作,在调试模式下运行导入的线程从未启动,不确定出了什么问题。为什么在这种情况下垃圾回收不起作用??? - Rick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接