Обновление (1 декабря 2009 г.):
Я хотел бы изменить этот ответ и признать, что первоначальный ответ был ошибочным.
Первоначальный анализ действительно применяется к объектам, которые требуют доработки, и точка зрения, что практики не должны приниматься на поверхности без точного, глубокого понимания, остается в силе.
Однако оказывается, что DataSets, DataViews, DataTables подавляют финализацию в своих конструкторах - вот почему вызов Dispose () для них явно ничего не делает.
Предположительно, это происходит потому, что у них нет неуправляемых ресурсов; поэтому, несмотря на тот факт, что MarshalByValueComponent учитывает неуправляемые ресурсы, эти конкретные реализации не нуждаются и поэтому могут отказаться от завершения.
(То, что авторы .NET позаботятся о том, чтобы подавить финализацию для тех типов, которые обычно занимают больше всего памяти, говорит о важности этой практики в целом для финализуемых типов.)
Несмотря на то, что эти детали все еще недостаточно документированы с момента создания .NET Framework (почти 8 лет назад), довольно удивительно (что вы по сути оставлены на своих собственных устройствах, чтобы просеивать хотя и противоречивые, неоднозначные материалы, чтобы собрать воедино кусочки). иногда разочаровывает, но обеспечивает более полное понимание структуры, на которую мы полагаемся каждый день).
После большого чтения, вот мое понимание:
Если объект требует финализации, он может занимать память дольше, чем нужно - вот почему: a) любой тип, который определяет деструктор (или наследует от типа, который определяет деструктор), считается финализуемым; б) При выделении (до запуска конструктора) указатель помещается в очередь финализации; c) Для финализуемого объекта обычно требуется 2 коллекции (вместо стандартной 1); d) Подавление финализации не удаляет объект из очереди финализации (как сообщает! FinalizeQueue в SOS) Эта команда вводит в заблуждение; Знание того, какие объекты находятся в очереди завершения (само по себе), не помогает; Было бы полезно знать, какие объекты находятся в очереди завершения и все еще требуют завершения (есть ли команда для этого?)
Подавление завершения выключает немного в заголовке объекта, указывая среде выполнения, что ему не нужно вызывать свой Finalizer (не нужно перемещать очередь FReachable); Он остается в очереди Финализации (и продолжает сообщаться! FinalizeQueue в SOS)
Классы DataTable, DataSet, DataView имеют корни в MarshalByValueComponent, финализируемом объекте, который может (потенциально) обрабатывать неуправляемые ресурсы.
- Поскольку DataTable, DataSet, DataView не представляют неуправляемые ресурсы, они подавляют завершение в своих конструкторах
- Хотя это необычный шаблон, он освобождает вызывающего абонента от необходимости беспокоиться о вызове Dispose после использования.
- Это и тот факт, что DataTable потенциально могут совместно использоваться различными DataSets, вероятно, поэтому DataSets не заботятся о том, чтобы избавиться от дочерних DataTables.
- Это также означает, что эти объекты появятся под! FinalizeQueue в SOS
- Тем не менее, эти объекты должны быть восстановлены после одной коллекции, как и их не финализируемые аналоги
4 (новые ссылки):
Оригинальный ответ:
Есть много вводящих в заблуждение и вообще очень плохих ответов на этот вопрос - любой, кто приземлился здесь, должен игнорировать шум и внимательно прочитать ссылки ниже.
Без сомнения, Dispose должен вызываться для любых объектов Finalizable.
DataTables являются Завершаемыми.
Вызов Dispose значительно ускоряет восстановление памяти.
MarshalByValueComponent вызывает GC.SuppressFinalize (this) в своем Dispose () - пропустить это означает, что нужно ждать десятки, если не сотни коллекций Gen0, прежде чем память будет освобождена:
С этим базовым пониманием завершения мы уже можем вывести некоторые очень важные вещи:
Во-первых, объекты, которые требуют доработки, живут дольше, чем объекты, которые этого не делают. На самом деле они могут жить намного дольше. Например, предположим, что объект в gen2 должен быть завершен. Завершение будет запланировано, но объект все еще находится в gen2, поэтому он не будет повторно собран до следующей коллекции gen2. Это действительно может быть очень долго, и, на самом деле, если дела пойдут хорошо, это будет долгое время, потому что коллекции gen2 дорогостоящие, и поэтому мы хотим, чтобы они происходили очень редко. Старые объекты, нуждающиеся в доработке, могут ждать десятки, если не сотни коллекций gen0, прежде чем освободить их пространство.
Во-вторых, объекты, которые требуют доработки, наносят сопутствующий ущерб. Поскольку внутренние указатели на объекты должны оставаться действительными, в памяти останутся не только объекты, которые непосредственно нуждаются в финализации, но и все, на что ссылается объект, прямо или косвенно, также останется в памяти. Если бы огромное дерево объектов было привязано к одному объекту, который требовал завершения, тогда все дерево задержалось бы, возможно, на долгое время, как мы только что обсуждали. Поэтому важно экономно использовать финализаторы и размещать их на объектах, которые имеют как можно меньше внутренних указателей на объекты. В приведенном мною примере дерева вы легко можете избежать этой проблемы, переместив ресурсы, нуждающиеся в финализации, в отдельный объект и сохранив ссылку на этот объект в корне дерева.
Наконец, объекты, нуждающиеся в финализации, создают работу для потока финализатора. Если ваш процесс финализации сложен, один и единственный поток финализатора будет тратить много времени на выполнение этих шагов, что может вызвать отставание в работе и, следовательно, привести к задержке большего количества объектов в ожидании завершения. Поэтому очень важно, чтобы финализаторы выполняли как можно меньше работы. Помните также, что хотя все указатели объектов остаются действительными во время финализации, возможно, эти указатели приводят к объектам, которые уже были завершены и, следовательно, могут быть менее чем полезными. Как правило, безопаснее избегать следования указателям объектов в коде финализации, даже если указатели действительны. Безопасный короткий путь к коду финализации является лучшим.
Возьмите его у кого-то, кто видел сотни МБ не ссылочных DataTables в Gen2: это очень важно и совершенно не замечено в ответах в этой теме.
Ссылки:
1 -
http://msdn.microsoft.com/en-us/library/ms973837.aspx
2 -
http://vineetgupta.spaces.live.com/blog/cns!8DE4BDC896BEE1AD!1104.entry
http://www.dotnetfunda.com/articles/article524-net-best-practice-no-2-improve-garbage -collector-производительность с помощью-finalizedispose-pattern.aspx
3 -
http://codeidol.com/csharp/net-framework/Inside-the-CLR/Automatic-Memory-Management/