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,瑞克

经过 Xamarin 支持的大量敲击和出色的帮助之后 - 答案是将方法包装在using (var pool = new NSAutoreleasePool ())

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

4

1 回答 1

3

这是相当消耗内存的。base64 stringbyte[]数组, the NSData, the UIImage, the second NSData, the secondbyte[]数组。这是您正在处理的图像所需内存的许多倍。

根据代码的调用方式(例如,在一堆图像上循环),您分配内存的速度可能比 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[]在可能的情况下重用第二个缓冲区),但我们需要更多地了解代码是如何使用的。

于 2012-10-20T01:14:17.510 回答