2008-12-17 52 views
4

在連續實例化一個com-wrapper並讓GC收集它(不是強制)的同時,我有一個奇怪的現象。GC在一段時間後包含大量固定對象

我在WinCE x86上測試.net cf。使用.net Compact框架遠程監視器監視性能。使用平臺構建器工具包中的Windows CE Remote性能監視器跟蹤本機內存。

在第一個1000創建的實例在性能監視器每個櫃檯似乎確定:

  • GC堆上升和下降,但平均保持不變
  • 固定的對象是0
  • 本機內存保持相同的平均
  • ...

然而,經過這些1000(大約)針扎對象計數器只升不計在以後再下降。但內存使用情況保持不變。

我不知道從這些信息中得出什麼結論......這是計數器中的錯誤,這是我軟件中的錯誤嗎?

[編輯]

我也注意到,固定的對象計數器開始儘快上去的總字節數在使用GC穩定後,如不通過壓實機櫃臺移動的物體。

The graphic of the counters http://files.stormenet.be/gc_pinnedobj.jpg

[/編輯]

這裏涉及的代碼:

private void pButton6_Click(object sender, EventArgs e) { 
     if (_running) { 
      _running = false; 
      return; 
     } 
     _loopcount = 0; 
     _running = true; 

     Thread d = new Thread(new ThreadStart(LoopRun)); 
     d.Start(); 
    } 

    private void LoopRun() { 
     while (_running) { 
      CreateInstances(); 
      _loopcount++; 
      RefreshLabel(); 
     } 
    } 

    void CreateInstances() { 
     List<Ppb.Drawing.Image> list = new List<Ppb.Drawing.Image>(); 
     for (int i = 0; i < 10; i++) { 
      Ppb.Drawing.Image g = resourcesObj.someBitmap; 
      list.Add(g); 
     } 

    } 

Image對象包含一個AlphaImage:

public sealed class AlphaImage : IDisposable { 
    IImage _image; 
    Size _size; 
    IntPtr _bufferPtr; 

    public static AlphaImage CreateFromBuffer(byte[] buffer, long size) { 
     AlphaImage instance = new AlphaImage(); 
     IImage img; 
     instance._bufferPtr = Marshal.AllocHGlobal((int)size); 
     Marshal.Copy(buffer, 0, instance._bufferPtr, (int)size); 
     GetIImagingFactory().CreateImageFromBuffer(instance._bufferPtr, (uint)size, BufferDisposalFlag.BufferDisposalFlagGlobalFree, out img); 
     instance.SetImage(img); 
     return instance; 
    } 

    void SetImage(IImage image) { 
     _image = image; 
     ImageInfo imgInfo; 
     _image.GetImageInfo(out imgInfo); 
     _size = new Size((int)imgInfo.Width, (int)imgInfo.Height); 
    } 

    ~AlphaImage() { 
     Dispose(); 
    } 

    #region IDisposable Members 

    public void Dispose() { 
     Marshal.FinalReleaseComObject(_image); 
    } 
} 

回答

3

我懷疑這是RPM中的錯誤。我們在這裏沒有任何洞察Ppb.Drawing的東西。我發現潛在問題的地方是GetIImagingFactory調用。它有什麼作用?這可能只是一個單身的getter,但這是我追求的東西。

我也看到一個AllochHGlobal,但是我看不到分配得到釋放。現在這是我關注的地方。

4

嗯,有一個錯誤的代碼,因爲你創建了很多IDisposable實例,從來沒有調用Dispose。我希望終結者最終能夠踢進,但他們不應該是真的有必要。在你的生產代碼中,你是否恰當地處理了一切 - 如果沒有,你有什麼理由不能?

如果你在AlphaImage終結器(檢測AppDomain卸載和應用程序關閉,並沒有在這些情況下登錄!)進行一些日誌記錄是否顯示被調用的終結器?

編輯:一個潛在的問題,這可能不是咬你,但可能是值得的固定反正 - 如果調用CreateImageFromBuffer出於某種原因失敗時,你還是自己用AllocHGlobal創建的內存,這將是目前泄露。我懷疑這不是問題,或者它會更加壯觀,但值得思考。

+0

正在調用終結器(如果它不會在幾秒鐘內失效)。 實際上,在調用AlphaImage Dispose的AlphaImage類中有一個Image類包裝器。 – Stormenet 2008-12-17 11:38:13

+0

不過,你不應該指望終結者 - 這是IDisposable的用途。 您應該使用using(image){...}構造來確保儘快調用Dispose方法。此外,在Dispose()中使用GC.SuppressFinalize(),以便終止對象不會被調用。 – configurator 2008-12-17 13:00:38