2010-01-07 5 views
6

Я экспериментировал с способами избавиться от утечек памяти в своем приложении на днях, когда понял, что практически ничего не знаю о очистке моих ресурсов. Я сделал некоторые исследования и надеялся, что просто вызов .dispose() решит все мои проблемы. У нас есть таблица в нашей базе данных, которая содержит около 65 000 записей. Очевидно, что когда я заполняю свой набор данных из адаптера данных, использование памяти может стать довольно высоким. Когда я назвал метод dispose в наборе данных, я был удивлен, узнав, что NONE из памяти освобожден. Почему это случилось? Очистка набора данных также не помогает.Использует ли метод .dispose() вообще?

ответ

25

IDisposable и, следовательно, Dispose не используется для уменьшения давления памяти, хотя в некоторых случаях он может использоваться, но вместо этого используется для детерминированной очистки.

Рассмотрите это, вы создаете объект, который поддерживает активное и открытое соединение с вашим сервером базы данных. Это соединение использует ресурсы как на вашем компьютере, так и на сервере.

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

Он используется для очистки ресурсов, управляемых объектом.

Он, однако, не освободит управляемую память, выделенную объекту. Это по-прежнему остается сборщику мусора, который в следующий раз начнется, чтобы сделать это.

У вас на самом деле проблема с памятью, или вы просто смотрите на использование памяти в диспетчере задач или подобное, и переходите «это немного высоко».?

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

Позвольте мне объяснить, что я имею в виду под «бегом реже».

Если на вашем компьютере имеется 8 ГБ памяти и работает только Windows и Notepad, большая часть этой памяти будет доступна. Когда вы запускаете свою программу, даже если она загружает небольшие блоки данных в память, вы можете продолжать делать это в течение длительного времени, а использование памяти будет неуклонно расти. Точно, когда GC заработает и попытается уменьшить объем памяти, я не знаю, но я могу почти гарантировать вам, что вы будете удивляться, почему он становится таким высоким.

Давайте просто ради аргумента скажем, что ваша программа в конечном итоге будет использовать 2 ГБ памяти.

Теперь, если вы запустите свою программу на компьютере с меньшим объемом памяти, GC будет происходить чаще и будет работать на нижнем пределе, что может снизить использование памяти ниже 500 МБ или, возможно, даже меньше.

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

+0

Моя программа может достигать 700,164k. Нехорошо, если у моих клиентов могут быть компьютеры с более низким уровнем. – broke

+6

, что означает, что вы не читали мой ответ. Попробуйте загрузить несколько крупных приложений, чтобы до запуска вашей собственной программы у вас было менее 700,164k доступной памяти (включая виртуальную память). Затем попробуйте загрузить его, возможно, он по-прежнему будет работать, если вы не загружаете больше, чем данные в память для использования, и в этом случае gc вообще не поможет, вам просто нужно уменьшить объем обрабатываемых данных в любой момент времени. –

+0

Хорошо, дайте ему попробовать. – broke

4

Вызов Dispose() будет освобождать неуправляемые ресурсы, такие как дескрипторы файлов, соединения с базой данных, неуправляемая память и т. Д. Это будет не релиз сборщика мусора.

Сбор собранных мусора будет выпущен только в следующей коллекции. Обычно, когда память домена приложения полностью заполняется.

3

Я собираюсь указать что-то здесь, о котором не было сказано в явном виде: вызов Dispose() будет очищать (бесплатно) неуправляемые ресурсы, если разработчик компонента закодировал его.

Что я имею в виду следующее: если вы подозреваете, что у вас есть утечка памяти, вызывая Dispose() не собирается это исправить если оригинальный разработчик сделал паршивую работу и не правильно высвободить неуправляемые ресурсы. Побольше информации, check this blog post. Обратите внимание на инструкцию Поведение Dispose определено разработчиком.

1

Некоторые объекты будут просить одно или несколько других лиц сделать что-либо от его имени до дальнейшего уведомления, в ущерб другим объектам. Если бы объект, который сделал это, исчезнет, ​​не сообщив прежним организациям о том, что их услуги больше не нужны, эти организации будут продолжать бесполезно действовать от имени объекта, который больше не нужен им, для дальнейшего ущерба другим объектам, которые захотят использовать их.

Во многих случаях для объекта «Джордж», чтобы сообщить внешнему сущности «Джо», что его услуги больше не нужны, Джордж должен был знать, что его услуги больше не нужны. Есть два нормальных средства, через которые это может произойти в .NET, финализация и IDIsposable.

Если объект переопределяет метод, называемый Finalize, то при создании объекта сборщик мусора .NET добавит его в список объектов с зарегистрированными финализаторами. Если ГК обнаруживает, что не существует привязанной ссылки на объект, отличный от этого списка, GC удалит объект из этого списка и добавит его в строго корневую очередь объектов, которые должны иметь метод Finalize, вызываемый как можно скорее. Такой объект затем может использовать свой метод Finalize для информирования других объектов о том, что их услуги больше не требуются.

Хотя очистка, основанная на финализации, может иногда работать, нет гарантии своевременности. В какой-то момент во время разработки .net Microsoft предположила, что окончательная доработка будет основным методом очистки, но по целому ряду причин на нее нельзя положиться.

Другой подход к очистке, который должен быть в центре внимания ваших усилий, - IDisposable. В принципе идея IDisposable проста: для каждого объекта, который реализует IDisposable, должен существовать один объект (как правило, объект или область вложенного выполнения), который отвечает за то, чтобы метод объекта был вызван в течение всего времени жизни (что подразумевало бы когда-нибудь, пока ссылка на объект все еще существует), и предпочтительно, как только код может сказать, что услуги объекта больше не требуются.

Отметьте, что IDisposable.Dispose обычно обещает, что любые внешние субъекты, которым было предложено что-то сделать от имени объекта, будет сказано, что им больше не нужно это делать, но такое обещание не означает, что количество объектов не является -нуль. Если объект не просил какие-либо внешние организации делать что-либо от его имени, то предоставление сообщения «всем» таким объектам вовсе не требует каких-либо действий.С другой стороны, тот факт, что метод Dispose ничего не может поделать в некоторых случаях, не означает, что он ни в чем не гарантирует ничего, кроме того, что отказ назвать его в тех случаях, когда он будет делать что-то, не будет пагубные последствия.

Смежные вопросы