4

我使用 3rd 方库,它是原生 dll 的包装器。该库包含一个类型XImageXImage一些属性和一个IntPtr Data()方法。XImage也实现IDisposable了,但我不知道它是否正确实现。

我从 TCP 连接中获得了许多XImages 并将它们显示为PictureBox.

我曾经将 'XImage' 转换为System.Drawing.Image并在 a 中查看它们,PictureBox但我得到了AccessViolationException.

所以我做了一个包装,XImage叫做Frame.

public class Frame : IDisposable
{
  public uint size { get; private set; }
  private Image image;
  public XImage XImage { get; set; }
  public Image Image { get { return image ?? (image = GetBitmap(this.XImage)); } }
  public DateTime Time { get; set; }

   public Frame(XImage xImage)
  {
    this.XImage = xImage;
    this.size = XImage.ImageBufferSize();
    GC.AddMemoryPressure(size);
  }


  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }

  ~Frame()
  {
    Dispose(false);
  }

  protected virtual void Dispose(bool disposing)
  {
    if (disposing)
    {
      try
      {
        image.Dispose();
      }
      catch { }
      finally
      {
        image = null;
      }
      try
      {
        MImage.Dispose();
      }
      catch { }
      finally { XImage = null; }
    }
    GC.RemoveMemoryPressure(size);
  }
}

并通过处理对Frame我的引用解决了AccessViolationException. 现在我有另一个问题,当我从 Visual Studio 运行程序时(F5 - 开始调试)一切都很好,但是当我从.exe文件或(ctrl + F5 - 开始而不调试)运行它时,内存使用量越来越大直到我得到OutOfMemoryException.(Biuld Configuration: Release - X86)。我应该怎么办 ?

- - 编辑 - -

我发现GC.AddMemoryPressure或者GC.RemoveMemoryPressure只是让垃圾收集更频繁地运行,我现在的问题是我有一些小对象,这些小对象有一个大型非托管内存的句柄,而 GC 没有收集这些小对象。

---- EDIT ----
调用GC.Collect会在运行时解决问题,我设置了一个定时器并GC.Collect定期调用,但它会使应用程序冻结一小段时间,所以我不想使用这种方法。

4

1 回答 1

0

我发现它GC有局限性,在非常重的压力和内存密集型应用程序下可能无法很好地工作。我有一个应用程序不直接对非托管资源、所有标准 .NET 组件执行任何操作,并且它仍然会阻塞内存。它可以使用 GB 的 RAM,但不是因为需要巨大的内存,而是因为大对象的创建和销毁速度相对较快,而且显然没有经常收集。应用程序没有内存泄漏,因为它在强制收集时全部释放。看起来GC并不总是能够按时收集未使用的对象,即之前OutOfMemoryException。它等待找到最好的时刻,但在它下定决心之前为时已晚。当我定期强制收集时,应用程序运行没有问题。

值得一提的是,OutOfMemoryException这并不总是意味着您实际上没有可用内存。这也可能意味着没有足够大的连续内存块可用。尤其是在处理视频和图像时可能会出现这种情况。GC可能会认为仍有大量可用内存,但对于您的应用程序来说太碎片化了。我确信GC会考虑到碎片化,但它可能并不总是正确。

如果您确定库不是问题,我的建议是更多地尝试使用内存压力方法(AddMemoryPressureRemoveMemoryPressure)以帮助GC按时完成工作。它可能会解决您的问题,因为您使用的非托管库可能正在处理大量的内存GC。或者像你一样做GC.Collect。手动收集可能并不理想,但我相信在某些情况下它是合理的。当然,确实希望手动收集大量对象可能会对您的应用程序性能产生影响。

编辑

如果手动收集对性能影响太大,请尝试使用重载版本GC.Collect,让您有更多控制权。

于 2012-05-14T10:16:45.290 回答