Как да предотвратя изтичане на памет с UIImage.FromImage(context.ToImage())?

Имам следната функция за преобразуване на байтов масив от пиксели в изображение. Имам обаче изтичане на памет в реда:

unpackedImage = UIImage.FromImage(context.ToImage());

Когато коментирам реда по-горе, течът изчезва. Изтичането е толкова лошо, че iOS убива приложението ми в рамките на около 30 секунди след стартиране. Това е заради този ред код.

Как да предотвратя това изтичане на памет? Има ли по-добър начин да направя това, което се опитвам да направя?

    public static void DrawCustomImage2(IntPtr buffer, int width, int height, int bytesPerRow, CGColorSpace colSpace, byte[] rawPixels, ref UIImage unpackedImage)
    {
        GCHandle pinnedArray = GCHandle.Alloc(rawPixels, GCHandleType.Pinned);
        IntPtr pointer = pinnedArray.AddrOfPinnedObject();

        // Set a grayscale drawing context using the image buffer
        CGBitmapContext context = new CGBitmapContext(pointer, width, height, 8, bytesPerRow, colSpace, CGImageAlphaInfo.None);

        // Turning off interpolation and Antialiasing is supposed to speed things up
        context.InterpolationQuality = CGInterpolationQuality.None;
        context.SetAllowsAntialiasing(false);

        try
        {
            unpackedImage = UIImage.FromImage(context.ToImage());   // Convert the drawing context to an image and set it as the unpacked image
        } finally
        {
            pinnedArray.Free();
            if (context != null)
                context.Dispose();
        }
    }

Ето екранната снимка на профилирането (всички маркирани елементи изчезват, когато критичният ред от код бъде коментиран). Можете да видите как маркираните елементи (особено Malloc) растат с течение на времето.

Екранна снимка за профилиране

Ето увеличения изглед на Malloc 1.50KB. Можете да видите в панела с разширени подробности вдясно, че извиква CGBitmapContextCreateImage и CGDataProviderCreateWithCopyOfData и след това malloc. Екранна снимка за профилиране на Malloc 1,50 KB

Ето екранната снимка на профилирането с предложението на Ролф. Пуснах цикъла на изображението два пъти. Можете да видите, че почиства допълнителната памет в края на първия цикъл, но системата не я изчисти достатъчно бързо втория път и iOS уби приложението ми (можете да видите предупредителните знаци за недостатъчна памет в горния десен ъгъл ъгъл). въведете описание на изображението тук


person nbonwit    schedule 22.05.2012    source източник


Отговори (1)


Направете го така:

using (var pool = new NSAutoreleasePool ()) {
    using (var img = context.ToImage ()) {
        unpackedImage = UIImage.FromImage (img); 
    }
}
person Rolf Bjarne Kvinge    schedule 22.05.2012
comment
Вашето предложение проработи... можете да видите от екранната снимка по-горе, че изчисти паметта в края на моя цикъл, но това не беше достатъчно добро за втория цикъл и iOS уби приложението. Как мога да го накарам да изчисти паметта в различни точки в моя цикъл? - person nbonwit; 22.05.2012
comment
Поставих ръчен GC.Collect() в блока finally и сега изглежда всичко върви добре! Благодаря много за бързата ви помощ!! Има ли по-добър начин да атакувате това вместо изрично извикване на GC.Collect()? - person nbonwit; 23.05.2012