Member 11799596 Ответов: 1

Почему после вызова dispose on bitmap object объекты GDI не освобождаются сразу


Я создаю растровый объект и из этого растрового объекта создаю значок, а затем размещаю их соответствующим образом. Во время выполнения кода я собирал количество объектов GDI после каждой операции GDI. Заметил, что после вызова Dispose для объекта Bitmap количество объектов GDI остается прежним.

class Icon_ResouceLeak
 {
     static void Main(string[] args)
     {
         // the program starts with 18 GDI objects..

         var bmp = new Bitmap("imagePath");
         // 25 GDI objects..

         IntPtr ptr = bmp.GetHicon();
         // 30 GDI Objects..

         Icon newIcon = Icon.FromHandle(ptr);

         var clonedIcon = (Icon)newIcon.Clone();
         // 33 GDI objects..

         DestroyIcon(newIcon.Handle);
         // 30 GDI objects ..

         clonedIcon.Dispose();
         // 27 GDI objects ..

         newIcon.Dispose();
         // 27 GDI objects..

         bmp.Dispose();
         // still 27 GDI objects? 
     }

     [DllImport("user32.dll", CharSet = CharSet.Auto)]
     extern static bool DestroyIcon(IntPtr handle);
 }


Что я уже пробовал:


bmp.Dispose() вызывает изображение.Диспсо(). Который внутренне вызывает SafeNativeMethods.Gdip.GdipDisposeImage(new HandleRef(this, nativeImage));
если это так, то почему он не освобождается.

1 Ответов

Рейтинг:
1

Member 11799596

Я понимаю это после иконы.FromHandle, поле ownHandle является ложным, и поэтому Dispose from FromHandle не вызовет DestroyIcon. Поэтому необходимо вызвать как DetroyIcon, так и Dispose.

Здесь мое сомнение другое. Почему после вызова БМП.Dispose() количество GDI не уменьшается.

RickZeeland

Если вы звоните из C#, это может быть связано с сборщиком мусора, это может занять некоторое время до очистки.

Member 11799596

С Dispose нам нужно все еще ждать GC. Я немного запутался в этом вопросе.
Даже если вы видите реализацию Dispose образа, она вызывает SafeNativeMethods.Gdip.GdipDisposeImage(new HandleRef(this, nativeImage)), а затем SuppressFinalize.

RickZeeland

System.GC.Collect() принудительно запускает сборщик мусора, но Microsoft не рекомендует этого делать.

Member 11799596

Мне до сих пор не ясна причина, по которой после вызова Dispose на Bitmap количество объектов GDI не уменьшается.

RickZeeland

Похоже, что здесь недостаточно опыта работы с CodeProject, чтобы помочь вам в дальнейшем, может быть, вы можете попробовать другой сайт, такой как StackOverflow, или, может быть, форум Microsoft, удачи !