GDI обрабатывает в приложении DotNET - PullRequest
6 голосов
/ 20 марта 2010

Моя чистая библиотека DotNET работает как плагин внутри неуправляемого настольного приложения. Я получаю стабильный (хотя и небольшой) поток отчетов о сбоях, которые, кажется, указывают на проблему с дескрипторами GDI (шрифты в сообщениях об ошибках и т. Д., Возвращающиеся к системному шрифту, отображение всех видов элементов управления, сбой, массовый сбой вскоре ).

У моих форм мало элементов управления, но я много рисую в GDI + в пользовательских элементах управления. Какой хороший способ узнать, сколько ручек я использую или даже подтекает?

Спасибо, David

Ответы [ 7 ]

5 голосов
/ 03 марта 2012

Начиная с GDIView из ответа Рэя Веги, я нашел этот совет :

[DllImport("User32")] 
extern public static int GetGuiResources(IntPtr hProcess, int uiFlags);

  public static void GetGuiResourcesGDICount()      
  { 
      //Return the count of GDI objects.          
      Console.WriteLine("GDICount"+GetGuiResources(System.Diagnostics.Process.GetCurrentProcess().Handle, 0));      
  }

  private void button1_Click(object sender, System.EventArgs e)
  {
      GetGuiResourcesGDICount();
  }

GDIView сообщил, что это были объекты шрифта, которые просочились; Затем я добавил вызовы к GetGuiResources в наш код регистрации, чтобы определить момент запуска создания объекта.

В нашем случае текст элемента управления Label обновлялся, когда его родительский элемент UserControl был скрыт в фоновом окне. Это может привести к утечке дескрипторов шрифта в GDI. Чтобы исправить это, мы изменили нашу логику, чтобы она не обновляла Label, если она не была видна в данный момент на экране. Чтобы определить, была ли она видимой, мы ведем учет того, когда UserControl был последний раз нарисован.

3 голосов
/ 07 апреля 2010

Взгляните на GDIView (это бесплатно):

GDIView - это уникальный инструмент, который отображает список ручек GDI (кисти, ручки, шрифты, растровые изображения и др.) открывается каждым процессом. Отображает общее количество для каждого типа GDI обрабатывать, а также подробно информация о каждой ручке. это Инструмент может быть полезен для разработчиков, которые необходимо проследить утечку ресурсов GDI в их программное обеспечение.

альтернативный текст http://www.nirsoft.net/utils/gdiview.gif

Обратите внимание , что автоматическое обновление по умолчанию отключено, но его можно включить и настроить для определенных интервалов: Options -> Auto Refresh -> Every [N] seconds

3 голосов
/ 20 марта 2010

Помимо монитора производительности, вы можете попробовать старый добрый диспетчер задач.

Проверьте вкладку Процесс , щелкните View> Select Columns... и проверьте объекты GDI.

2 голосов
/ 20 марта 2010

В прошлом мне приходилось сталкиваться с такой же проблемой. Чтобы проверить, сколько объектов GDI выделяет ваше приложение, вы можете использовать бесплатный инструмент под названием GDIUsage .

В моем случае приложение зависало, поскольку оно выделяло более 10.000 объектов GDI , что является жестким ограничением в Windows XP. Возможно, стоит посмотреть на это.

Я писал об этой проблеме здесь:
http://megakemp.com/2009/02/25/gdi-memory-leak-in-windows-forms/

1 голос
/ 07 августа 2010

GDIObj , бесплатная утилита, предоставленная Фэн Юанем в качестве примера программы для его книги, Программирование графики Windows: Win32 GDI и DirectDraw могут быть полезны.

В отличие от диспетчера задач, он обеспечивает подсчет дальнейшей разбивки различных типов дескрипторов GDI, включая DC, Region, Bitmap, Palette, Font, Brush и т. Д.

(Тем не менее, он предоставляет только информацию о количестве, в то время как GDIView предоставляет более подробную информацию об дескрипторах.)

1 голос
/ 20 марта 2010

Если вы этого еще не сделали, обязательно вызовите IDisposable.Dispose для всех используемых вами объектов рисования GDI +. Обычно вы делаете это с помощью конструкции C # using, например ::

using(Brush brush = ...)
{
    ...
}

Инструменты статического анализа кода, такие как FxCop или версия, встроенная в редакции Team System Visual Studio, могут помочь обнаружить случаи, когда вам не удается вызвать Dispose.

Неудачный вызов метода Dispose является потенциальной утечкой дескриптора, так как дескриптор не будет возвращен, пока сборщик мусора не сочтет нужным.

1 голос
/ 20 марта 2010

Это легко увидеть из TaskMgr.exe, вкладка Процессы. Просмотр + Выбор столбцов, отметьте объекты GDI.

Ваше описание действительно соответствует утечке ручки. В управляемой программе этого не должно быть, финализатор должен позаботиться о том, чтобы вы забыли вызвать Dispose () Если вы не потребляете много мусора в куче пространства. Это также могут быть ручки неуправляемой утечки приложений, они очень часто это делают.

...