@ Джастин
... так что, чтобы ответить на ваш вопрос, нет. Нет ничего плохого в том, чтобы зависеть от .NET Garbage Collector.Напротив, на самом деле.
Это ужасная практика - полагаться на то, что ГК очистит вас.К сожалению, вы рекомендуете это.Это может привести к утечке памяти, и да, в .NET есть как минимум 22 способа «утечки памяти».Я работал с огромным количеством клиентов, которые диагностировали как утечки управляемой, так и неуправляемой памяти, предлагая решения для них, и рассказали нескольким группам пользователей .NET о Advanced GC Internals и о том, как работает управление памятью изнутри GC и CLR.
@ OP: Вы должны вызвать Dispose () для DataTable и явно установить его равным нулю в конце цикла.Это явно говорит GC, что вы закончили с этим, и больше нет корневых ссылок на него.DataTable помещается на LOH из-за его большого размера.Если вы этого не сделаете, вы можете легко фрагментировать ваш LOH, что приведет к исключению OutOfMemoryException.Помните, что LOH никогда не уплотняется!
Дополнительные сведения см. В моем ответе по адресу
Что произойдет, если я не вызову Dispose для объекта пера?
@ Henk - Там есть взаимосвязь между IDisposable и управлением памятью;IDisposable допускает полуявное освобождение ресурсов (если реализовано правильно).А с ресурсами всегда связана какая-то управляемая и , как правило, неуправляемая память.
Несколько замечаний по поводу Dispose () и IDisposable здесь:
IDisposable обеспечивает удаление как Управляемой, так и Неуправляемой памяти.Утилизация неуправляемой памяти должна выполняться в методе Dispose, и вы должны предоставить Финализатор для вашей реализации IDisposable.
GC не вызывает для вас Dispose.
Если вы не вызываете Dispose (), GC отправляет его в очередь финализации и, в конечном счете, снова в очередь f-достижимости.Финализация заставляет объект выживать 2 коллекций, что означает, что он будет повышен до Gen1, если он был в Gen0, и до Gen2, если он был в Gen1.В вашем случае объект находится на LOH, поэтому он сохраняется до тех пор, пока не будет выполнен полный сборщик мусора (все поколения плюс LOH) дважды , что в «здоровом» приложении .NET представляет собой одну полную коллекциювыполняется ок.1 на каждые 100 коллекций.Поскольку в зависимости от вашей реализации на кучу LOH и GC оказывается большое давление, полные GC будут срабатывать чаще.Это нежелательно по соображениям производительности, поскольку полный сборщик мусора занимает гораздо больше времени.Кроме того, существует зависимость от того, какой тип GC вы используете, и используете ли вы LatencyModes (будьте очень осторожны с этим).Даже если вы используете Background GC (он заменил Concurrent GC в CLR 4.0), эфемерная коллекция (Gen0 и Gen1) по-прежнему блокирует / приостанавливает потоки.Это означает, что никакие распределения не могут быть выполнены в течение этого времени.Вы можете использовать PerfMon для мониторинга поведения использования памяти и активности GC в вашем приложении.Обратите внимание, что счетчики ГХ обновляются только после проведения ГХ.Для получения дополнительной информации о версиях GC см. Мой ответ на
Определение того, какой сборщик мусора работает .
Утилизация() немедленно высвобождает ресурсов , связанных с вашим объектом.Да, GC недетерминирован, но вызов Dispose () не вызывает GC!
Dispose () сообщает ГХ, что вы закончили с этим объектом, и его память может быть восстановлена в следующей коллекции для поколения, в котором этот объект живет .Если объект находится в Gen2 или в LOH, эта память не будет возвращена, если будет выполнена коллекция Gen0 или Gen1!
Финализатор работает в 1 потоке (независимо от версииИспользуемый GC и количество логических процессоров на машине.Если вы много занимаетесь в очередях Finalization и f-достижимости, у вас есть только 1 поток, обрабатывающий все готовое для Finalization, ваша производительность падает, вы знаете, куда ...*
Информацию о том, как правильно реализовать IDisposable, см. В моем блоге:
Как правильно реализовать шаблон IDisposable?