Общая ошибка произошла в GDI + при вызове Bitmap.GetHicon

Почему я получаю "Общая ошибка в GDI +" Исключение?

IntPtr hicon = tempBitmap.GetHicon();             
Icon bitmapIcon = Icon.FromHandle(hicon);            
return bitmapIcon;

Ошибка произошла, когда мое приложение было запущено более 30 минут. (Я преобразовываю System.Drawing.Bitmap в System.Drawing.Icon каждую секунду)

enter image description here

Ответ 1

Это вызвано утечкой рукоятки. Вы можете диагностировать утечку с помощью вкладки TaskMgr.exe, Processes. View + Select Columns and tick Handles, GDI Objects и USER Objects. Наблюдайте за этими столбцами во время работы вашей программы. Если моя догадка верна, вы увидите, что значение объектов GDI для вашего процесса неуклонно растет. Когда он достигает 10 000, шоу прекращается, Windows отказывается позволить вам просачивать больше объектов.

Раздел "Примечания" для Icon.FromHandle говорит:

При использовании этого метода вы должны удалить полученный значок с помощью метода DestroyIcon в Win32 API, чтобы обеспечить освобождение ресурсов.

Это хороший совет, но обычно довольно болезненный. Вы можете найти хак, чтобы заставить объект Icon владеть дескриптором и автоматически отпустить его в этом ответе. Соответствующий код находится после раздела "Invoke private Icon constructor".

Ответ 2

Вам, вероятно, потребуется очистить значок.

Пример Icon.FromHandle в MSDN показывает, как. К сожалению, для этого требуется PInvoke:

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

И затем внутри вашего метода:

IntPtr hicon = tempBitmap.GetHicon();             
Icon bitmapIcon = Icon.FromHandle(hicon);        

// And then somewhere later...
DestroyIcon(bitMapIcon.Handle);    

Если вы вызываете DestoryIcon, прежде чем использовать его, это может не сработать. Для моего собственного экземпляра этой проблемы я в конечном итоге сохранил ссылку на последний значок, который я создал, а затем набрал DestroyIcon в следующий раз, когда я сгенерировал значок.