当没有剩余内存时,.Net和Bitmap不会由GC自动处理
我想知道如何分配和处理分配给位图的内存在.NET中工作。
当我在一个函数的循环中做了大量的位图创build并连续调用它时,它会一直运行,直到某些时候Bitmap将不能分配给出指定大小的“无效参数”exception的内存。
如果我打电话给垃圾收集器,而它的工作。
用下面的代码你可以重新编译错误:
class BitmapObject { public bool Visible { get { return enb; } set { enb = value; } } private bool enb; private Bitmap bmp; public BitmapObject(int i, bool en) { enb = en; bmp = new Bitmap(i, i); } } class Pool<T> where T : BitmapObject { List<T> preallocatedBitmaps = new List<T>(); public void Fill() { Random r = new Random(); for (int i = 0; i < 500; i++) { BitmapObject item = new BitmapObject(500, r.NextDouble() > 0.5); preallocatedBitmaps.Add(item as T); } } public IEnumerable<T> Objects { get { foreach (T component in this.preallocatedBitmaps) { if (component.Visible) { yield return (T)component; } } } } } static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { for (int i = 0; i < 10; i++ ) { Test(); // without this it breaks //GC.Collect(); //GC.WaitForPendingFinalizers(); } Console.ReadKey(); } private static void Test() { Pool<BitmapObject> pool = new Pool<BitmapObject>(); pool.Fill(); for (int i = 0; i < 100; i++) { var visBitmaps = pool.Objects; // do something } } }
.NET Bitmap
类“封装了一个GDI +位图”,这意味着当你完成它的时候,你应该在一个Bitmap
上调用Dispose
,
“在释放最后一次引用Image之前总是调用Dispose,否则在垃圾回收器调用Image对象的Finalize方法之前,它所使用的资源将不会被释放。
Bitmap类不可避免地要停止忽略IDisposable的存在。 这是一个围绕GDI +对象的小包装类。 GDI +是非托pipe代码。 位图占用非托pipe内存。 当位图很大的时候很多。
.NET垃圾收集器确保非托pipe系统资源与终结器线程一起发布。 问题是,当您创build足够数量的托pipe对象来触发垃圾回收时,它只会触发行动。 这对于Bitmap类来说效果不佳,可以在垃圾收集堆的第0代填充之前创build数千个。 你可以到达那里之前用完非托pipe内存。
pipe理您使用的位图的生命周期是必需的。 当您不再使用Dispose()方法时,调用它。 这并不总是最好的解决scheme,如果您只是有太多的实时位图,您可能不得不重新考虑您的方法。 下一个解决scheme是64位操作系统。
你为什么不using
关键字。 只需将您的Bitmap对象封装在其中,编译器将确保调用Dispose方法。
它只是一个语法快捷方式
try { ... } finally { ...Dispose(); }