4

在不断实例化一个 com-wrapper 然后让 GC 收集它(不是强制)时,我有一个奇怪的现象。

我正在 WinCE x86 上的 .net cf 上对此进行测试。使用 .net Compact 框架远程监控器监控性能。使用平台构建器工具包中的 Windows CE 远程性能监视器跟踪本机内存。

在前 1000 个创建的实例中, perfmon 中的每个计数器似乎都正常:

  • GC 堆上升和下降,但平均值保持不变
  • 固定对象为 0
  • 本机内存保持相同的平均值
  • ...

但是,在这 1000 个(大约)之后,固定对象计数器会上升,并且永远不会再下降。但是,内存使用量保持不变。

我不知道从这些信息中得出什么结论...这是计数器中的错误,这是我的软件中的错误吗?

[编辑]

我确实注意到,一旦 GC 稳定后使用的总字节数与压缩器计数器未移动的对象一样,固定对象计数器开始上升。

计数器图形 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);
    }
}
4

2 回答 2

4

好吧,您的代码中存在一个错误,即您创建了很多 IDisposable 实例并且从不对它们调用 Dispose。我希望终结者最终会发挥作用,但它们不应该真的是必需的。在您的生产代码中,您是否适当地处理了所有内容 - 如果没有,是否有一些原因您不能?

如果您在 AlphaImage 终结器中添加了一些日志记录(检测 AppDomain 卸载和应用程序关闭并且在这些情况下不记录!)它是否显示终结器被调用?

编辑:一个潜在的问题可能不会对您造成困扰,但无论如何可能值得修复 - 如果对 CreateImageFromBuffer 的调用由于某种原因失败,您仍然拥有 AllocHGlobal 创建的内存,并且当前将被泄露。我怀疑这不是问题,否则它会爆炸得更壮观,但值得思考。

于 2008-12-17T10:59:57.703 回答
3

我怀疑这是 RPM 中的错误。我们在这里没有对 Ppb.Drawing 的任何见解。我看到潜在问题的地方是 GetIimagingFactory 调用。它有什么作用?它可能只是一个单例吸气剂,但这是我要追逐的东西。

我还看到了一个 AllochHGlobal,但我没有看到该分配被释放。现在,这就是我要关注的地方。

于 2008-12-17T12:19:57.417 回答