2009-03-13 2 views
3

Мне нужно избавиться от объекта, чтобы он мог освободить все, что ему принадлежит, но он не реализует IDisposable, поэтому я не могу использовать его в используемом блоке. Как я могу собрать сборщик мусора?Сбор мусора на одном объекте, C#

ответ

9

Вы можете принудительно собрать коллекцию с помощью GC.Collect(). Будьте очень осторожны, используя это, поскольку полная коллекция может занять некоторое время. Лучшей практикой является просто позволить GC определить, когда самое лучшее время для сбора.

Имеет ли объект неуправляемые ресурсы, но не реализует IDisposable? Если это так, это ошибка.

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

+0

Я думаю, его вопрос состоит в том, что он содержит управляемые ресурсы, но он использует много ресурсов, поэтому он хочет, чтобы они были выпущены немедленно, когда он больше не нуждается в этом объекте. – DevinB

+0

Если это так, пусть GC просто справится с этим. Если ресурс достаточно велик и оказывает достаточное давление памяти, он будет обрабатываться при следующем генераторе 0 GC. – Michael

+0

на самом деле, он содержит сокет, и я хочу, чтобы сокет был выпущен как можно скорее, но у меня нет доступа к самому закрытию сокета. – Malfist

0

Если объект выходит из сферы действия и не имеет внешних ссылок, он будет собран довольно быстро (вероятно, в следующей коллекции).

+0

Не обязательно. Например. если он уже переместился в генератор 2, это может занять некоторое время, и если есть ожидающий финализатор, нужны два сбора. –

2

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

Если у вас есть только собственная память, даже много ее, все, что вам нужно сделать, это убедиться, что объект выходит за рамки. Не звонок GC.Collect() — это одна из тех вещей, которые, если вы должны спросить, вы не должны этого делать.

+0

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

+0

Решение №1, которое является быстродействующим: вызов GC.Collect(); Решение №2, которое является долговременным (и правильным) исправлением: Ditch этой библиотеки и получить новый. –

+1

# 2 не всегда вариант :) – alchemical

2

Вы не можете выполнять сборку мусора на одном объекте. Вы можете запросить сбор мусора, вызвав GC.Collect(), но это повлияет на все объекты, подлежащие очистке. Он также сильно обескуражен, так как он может отрицательно повлиять на производительность последующих коллекций.

Кроме того, вызов Dispose на объект не очищает его память. Он позволяет только удалять ссылки на неуправляемые ресурсы. Например, вызов Dispose в StreamWriter закрывает поток и освобождает дескриптор файла Windows. Память для объекта на управляемой куче не восстанавливается до последующей сборки мусора.

Chris Sells также обсуждал это на .NET Rocks. Я думаю, что это было во время его первого появления, но этот вопрос, возможно, был вновь рассмотрен в последующих интервью.

Эта статья Франческо Balena также хорошая ссылка:

Когда и как использовать Dispose и Доработать в C# http://www.devx.com/dotnet/Article/33167/0/page/1

0

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

Сообщает нам немного больше об объекте и почему вы хотите это сделать. Мы можем сделать некоторые предложения, основанные на этом. Код всегда помогает. И в зависимости от объекта может быть метод Close или что-то подобное. Может быть, это нужно назвать. Если тип метода Close или Dispose отсутствует, вы, вероятно, не хотите полагаться на этот объект, так как вы, вероятно, получите утечку памяти, если на самом деле он содержит ресурсы, которые необходимо будет освободить.

-2

BEWARE: из ф ра г Enta Тион во многих случаях, GC.Collect() или некоторые IDisposal является не очень полезно, особенно для больших объектов (LOH для объектов ~ 80Kb +, не выполняет не уплотнению и подлежат высоких уровням фрагментации для многих случаев общего пользования), которые затем приводят к из памяти (OOM) вопросов даже с потенциально сотен MB бесплатно. По мере того, как время идет, вещи становятся больше, хотя, возможно, не этот размер (80 штук kb) для LOH, отнесенных к объектам, высокая степень Параллелизм вызывает этот вопрос из-за большего количества объектов за меньшее время (и, вероятно, меняется по размеру) инстанцирован/отпущена.

массив являются обычных подозреваемыми этой проблемы (это также часто трудно определить из-за неспецифические исключениями и утверждением от исполнения, что-то вроде «высоких% крупных фрагментации кучи объекта» будет swell), прогноз для кода, страдающего этой проблемой, - это реализовать агрессивную стратегию повторного использования.

Класс в Systems.Collections.Concurrent.ObjectPool из parallel extensions beta1 samples помогает (к сожалению, это не просто вездесущий шаблон, который я видел, как, возможно, некоторые присоединенные методы собственности/расширения?), Достаточно просто для добавления или повторной реализации для большинства проектов, вы назначаете генератор Func <> и используйте методы Get/Put helper для повторного использования вашего предыдущего объекта и отказались от обычной сборки мусора. Обычно достаточно сосредоточиться на массиве, а не на отдельных элементах массива.

Было бы неплохо, если бы .NET 4 обновил все методы .ToArray() везде, чтобы включить .ToArray (T target).

Получение повесить с помощью SOS/WinDbg (.loadby Сос mscoreei для CLRv4) проанализировать этот класс вопроса может помочь. Думая об этом, текущая система сбора мусора больше похожа на повторный цикл мусора (с использованием той же физической памяти), ObjectPool аналогичен повторному использованию мусора. Если кто-нибудь помнит 3 R, сокращение использования памяти также является хорошей идеей, для достижения производительности;)