Ошибка создания дескриптора окна (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, я просто дал форма вызвала ошибку непосредственно как форма запуска и попыталась запустить.. форма не загружалась и не отображала сообщение об ошибке! я вернулся и снова изменил форму запуска обратно на главную форму и запустился, тогда это было волшебство, когда я нажал на кнопку форма загружена без каких-либо сообщений об ошибках!!!.
не знаю, что изменилось позади, но все еще хорошо сейчас......