2012-07-22 69 views
1

以下代碼的一個變體用於工作,但現在我收到內存泄漏,如下面的屏幕截圖所示。我將代碼從另一個線程移至TimerElapsed事件(請參閱截圖中的堆棧跟蹤),對MD 3.0.3.4和MT 5.3.4進行了各種代碼更新和升級。不幸的是,我似乎無法弄清楚爲什麼它不再工作。恢復到從普通線程調用的代碼的先前版本似乎也不起作用。這是MD或MT當前版本中的錯誤嗎?單觸式內存泄漏

正如你所看到的,我使用NSAutoReleasePool以及在最後強制垃圾收集,它仍然不起作用!

編輯:我添加的代碼下面,從通過DrawCustomImage其聲明痕跡unpackedImage,然後進入SetImages()作爲「imageToSet」參數,然後進入窗格在overlayImage()的「覆蓋」參數。 SetImage在主線程中調用它內部的代碼,因爲當它最終調用UpdateLiveScreen(帶有最終的overlayedImage)時,它實際上會繪製到屏幕上。

static UIImage unpackedImage = new UIImage(); 

    public static void DrawCustomImage(IntPtr buffer, int width, int height, int bytesPerRow, CGColorSpace colSpace, byte[] rawPixels, ref UIImage unpackedImage) 
    { 
     using (var pool = new NSAutoreleasePool()) 
     { 
      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); 

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

    SetImages(labelText, symbolArray[0], unpackedImage, points); 

    public static void SetImages(String labelText, UIImage symbol, UIImage imageToSet, PointF[] points) 
    { 
     appReference.InvokeOnMainThread(delegate 
     { 
      int imageWidth = 716; 
      int imageHeight = (int)imageToSet.Size.Height; 
          int nextFreeMainImageColumn = 5; // This gets set dynamically, but is simplified here for readability 

      lock (displayLocker) 
      { 
       // Get the current doppler image 
       UIImage mainImage = GetMainImage(); 

       // Add the new imageToSet to the current image by overlaying it adjacent to the current image 
       UIImage overlayedImage = overlayImage(mainImage, imageToSet, 
            new RectangleF(0, 0, imageWidth, imageHeight), 
            new RectangleF(nextFreeMainImageColumn, 0, imageToSet.Size.Width, imageHeight)); 

       // Update the live screen with the updated image and frame number 
       LiveCont.UpdateLiveScreen(labelText, symbol, overlayedImage, points); 
      } 
     }); 
    } 

    public static UIImage overlayImage(UIImage image, UIImage overlay, RectangleF imageBoundingBox, RectangleF overlayBoundingBox) 
    { 
     int numBytes = 4; // Four bytes per pixel for a color image (Alpha, Red, Green, Blue) 
     int bytesPerRow = (int)imageBoundingBox.Width * numBytes; 

     // Set a color drawing context 
     CGBitmapContext context = new CGBitmapContext(
      IntPtr.Zero, 
      (int)imageBoundingBox.Width, 
      (int)imageBoundingBox.Height, 
      8, 
      bytesPerRow, 
      CGColorSpace.CreateDeviceRGB(), 
      CGImageAlphaInfo.NoneSkipFirst 
     ); 

     UIImage overlayedImage = null; 
     try 
     { 
      context.DrawImage(imageBoundingBox, image.CGImage);    // Draw the main image 
      context.DrawImage(overlayBoundingBox, overlay.CGImage);   // Draw the overlay 

      using (var img = context.ToImage()) 
      { 
       overlayedImage = UIImage.FromImage(img);     // Convert the context back to an image 
      } 
     } 
     finally 
     { 
      if (context != null) 
       context.Dispose(); 
      image.Dispose(); 
     } 

     return overlayedImage; 
    } 

enter image description here

+0

我回到了MT 5.2.12,問題消失了,所以MT 5.2.12和5.3.4之間的MT代碼中一定有一些錯誤。 – nbonwit 2012-07-22 02:22:36

回答

0

由於用於填充bug report

當您撥打電話ToImage(請參閱source)時,本機會撥打CGBitmapContextCreateImage(來自儀器的堆棧跟蹤)。該代碼在5.2.12和5.3之間沒有改變,所以它可能不是罪魁禍首。

管理GCImage不採取額外的關於手柄(true在.ctor使用)(見source,近期沒有任何變化)。

所以這需要我們從您的方法返回的unpackedImageUIImage。在此調用周圍使用自動 有一個變化(在5.3.x中)。

否則,在/你如何處理返回的unpackedImage結束(和哪個線程,例如CoreGraphics中是線程安全的,而UIKit的大多是不是)。

您可以添加顯示此代碼(在這裏或私人的bug報告)嗎?我不認爲問題出現在你的代碼中(因爲它在5.2.x上工作),但它會使跟蹤更容易。

請注意,調用GC.Collect是沒有幫助的(和它很少是),因爲情況下,您正在使用的所有執行IDisposable(其中一般立即資源的部署和取出完成步驟),並手動或處置這些using