Ошибка создания дескриптора окна (VB.NET)

У меня есть довольно большое приложение, написанное на VB.NET, которое, похоже, страдает от утечки памяти того или иного рода. Несколько раз в день у меня есть экземпляры этого приложения, которые аварийно завершают работу (по-видимому, наугад, но всегда после использования в течение почти дня). Я искал и читал много форумов и даже вопросы, задаваемые здесь на Stack Overflow об этой конкретной проблеме. Я определил, что это связано с утечкой памяти и обычно указывает либо на дескрипторы, превышающие 10000, либо на объекты, превышающие ограничение.

Я скачал memory pro filer и использовал его, чтобы найти и исправить несколько утечек памяти в программе, но это, похоже, не замедляло число ежедневных сбоев. Моя программа использует глобальную ловушку ошибок, чтобы регистрировать эти события и хранить информацию о них в базе данных. Теперь у меня есть данные за 2 месяца, но сообщение об ошибке на самом деле не помогает мне указать направление. Я недавно добавил возможность для этого глобального средства отслеживания ошибок регистрировать дескрипторы, которые есть у приложения, и до сих пор он был намного ниже порога 10 000 дескрипторов. Обычно это меньше 1000.

Короче говоря, мой вопрос таков. Есть ли какой-нибудь способ записать количество объектов GDI, чтобы я мог определить, не вызывает ли это мою программу? Существуют ли другие "объекты", которые могут вызывать утечку памяти и сбой, кроме этих двух, и могу ли я зарегистрировать их как-нибудь?

Я пытался читать столько, сколько я могу, и я просто не могу понять это, поэтому я ценю любое направление, которое вы можете дать мне. Похоже, что подобные проблемы мешают многим программам. Надеюсь, кто-то может помочь мне, и это может помочь другим в будущем.

Немного больше информации о моей программе и среде. Он в основном работает на 64-битных компьютерах с Windows 7 (хотя присутствуют некоторые машины Vista и XP), работает на платформе.NET 4.0. Проект состоит из нескольких сотен форм, классов и пользовательских элементов управления (созданных специально для этого проекта). Я использую.NET memory profiler 4.6 для проверки утечек памяти. Я выполнил то, что я считаю наиболее ресурсоемкими операциями на моем компьютере, более часа (открывая и впоследствии закрывая множество экранов, перебирая данные на концертах и ​​т. Д.), Наблюдая за ресурсами в диспетчере задач (Дескрипторы, потоки, объекты USER и объекты GDI), но ни один из них не превышает 1000.

Вот копия одного из журналов от события сбоя:

Loaded Assembly:   GlobalFuncs, Version=1.0.3391.14822, Culture=neutral, PublicKeyToken=null
Loaded Assembly:   Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Loaded Assembly:   mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly:   MySql.Data, Version=6.5.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d
Loaded Assembly:   SQL Database, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Loaded Assembly:   System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly:   System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Loaded Assembly:   System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly:   System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly:   System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Loaded Assembly:   System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Loaded Assembly:   System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Loaded Assembly:   System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly:   System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly:   System.Speech, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
Loaded Assembly:   System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly:   System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Loaded Assembly:   System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

OS Name:           Microsoft Windows 7 Professional 
OS Version:        6.1.7601.65536
OS Platform:       x64
Physical Memory:   1.91GB / 3.90GB (Free / Total)
Virtual Memory:    1.66GB / 2.00GB (Free / Total)

Error Output:
System.ComponentModel.Win32Exception (0x80004005): Error creating window handle.
   at System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)
   at System.Windows.Forms.Control.CreateHandle()
   at System.Windows.Forms.TextBoxBase.CreateHandle()
   at System.Windows.Forms.Control.get_Handle()
   at System.Windows.Forms.RichTextBox.get_TextLength()
   at System.Windows.Forms.TextBoxBase.AdjustSelectionStartAndEnd(Int32 selStart, Int32 selLength, Int32& start, Int32& end, Int32 textLen)
   at System.Windows.Forms.TextBoxBase.GetSelectionStartAndLength(Int32& start, Int32& length)
   at System.Windows.Forms.TextBoxBase.AppendText(String text)
   at SWOT.My.MyApplication.ShowDebugOutput(Exception ex)
   at SWOT.My.MyApplication.app_ThreadException(Object sender, ThreadExceptionEventArgs e)
   at System.Windows.Forms.Application.ThreadContext.OnThreadException(Exception t)
   at System.Windows.Forms.Control.WndProcException(Exception e)
   at System.Windows.Forms.Control.ControlNativeWindow.OnThreadException(Exception e)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.Run(ApplicationContext context)
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
   at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()

Единственное, что у меня было, - это то, что мой глобальный ловец ошибок падает при попытке загрузки, потому что не может создавать больше дескрипторов, и я каким-то образом теряю эту информацию. Но времена, когда он не дает сбоя и может регистрировать количество дескрипторов, довольно низок (sub 1000). Сборщик мусора высвобождает много ресурсов сразу после сбоя до того, как программа может записать большое количество дескрипторов? Я просто немного растерялся и запутался в данных, которые у меня есть.

2 ответа

Исходя из того факта, что в выводе об ошибке указано, что у вас достаточно много памяти (более 1 ГБ), а сообщение об ошибке "Ошибка создания дескриптора окна", я подозреваю, что ваше приложение сталкивается с проблемой не освобождения дескрипторов, а не освобождение памяти. Наиболее вероятная причина не освобождения дескрипторов - использование вызовов P/Invoke. Вы можете просто найти свой код для Declare а также DllImport чтобы увидеть, действительно ли вы используете какие-либо функции P/Invoke. Если это так, вам нужно будет сделать подробный обзор каждой функции, которую вы вызываете, и если она возвращает какие-либо дескрипторы (через IntPtr или классы, производные от SafeHandle). Если какой-либо из этих вызовов создает дескриптор, особенно дескриптор окна (часто сокращенно hWnd), вам необходимо убедиться, что ваш код освобождает hWnd.

Если вы не используете какой-либо код DllImport/P/Invoke, то, скорее всего, вы вызываете его косвенно через управляемый код, такой как создание нового System.Windows.Forms.Form или же System.Windows.Forms.Control -приобретенный класс (который также создает дескриптор окна) и не вызывающий Close или Dispose для него. Есть и другие вещи, которые тоже создают ручки, но они приходят на ум.

У меня было то же сообщение об ошибке, и я не уверен, что именно не так, но все же я хотел бы поделиться тем, как это было решено...

я не делал ничего особенного, но, как сказал Скотт, форма вызывается путем создания нового экземпляра и метода Form.show(), когда кнопка щелкает в основной форме, что я сделал вместо того, чтобы открывать форму по событию click, я просто дал форма вызвала ошибку непосредственно как форма запуска и попыталась запустить.. форма не загружалась и не отображала сообщение об ошибке! я вернулся и снова изменил форму запуска обратно на главную форму и запустился, тогда это было волшебство, когда я нажал на кнопку форма загружена без каких-либо сообщений об ошибках!!!.

не знаю, что изменилось позади, но все еще хорошо сейчас......

Другие вопросы по тегам