Часть того, что происходит в ГХ, состоит в том, что объекты в памяти поколенческие , так что ранние поколения собираются чаще, чем другие. Это помогает сохранить производительность, не пытаясь постоянно собирать долгоживущие объекты.
Имея это в виду, две вещи могут произойти, когда вы сами звоните GC.Collect()
. Во-первых, вы тратите больше времени на сборы. Это связано с тем, что обычные фоновые коллекции все равно будут происходить в дополнение к вашему ручному GC.Collect (). Во-вторых, вы будете держаться за память дольше , потому что вы ввели некоторые вещи в поколение более высокого порядка, которое не нужно было туда переходить. Другими словами, использование GC.Collect () самостоятельно почти всегда является плохой идеей.
Есть несколько случаев, когда сборщик мусора не всегда работает хорошо. Одним из них является куча больших объектов. Это специальное поколение для объектов, размер которых превышает определенный размер (80 000 байт, IIRC, но это может быть уже старым). Это поколение едва ли когда-либо собрано и почти никогда не уплотнено 1013 *. Это означает, что со временем вы можете получить много значительных дыр в памяти, которые не будут освобождены. Физическая память фактически не используется, и доступен для других процессов , но она все еще потребляет адресное пространство внутри вашего процесса, из которых вы по умолчанию ограничены 2 ГБ.
Это очень распространенный источник исключений OutOfMemory & mdash; на самом деле вы не используете столько памяти, но все это адресное пространство занято дырами в куче больших объектов. Безусловно самый распространенный способ, которым это происходит, - это многократное добавление к большим строкам или документам. Вероятно, это не вы, потому что в этом сценарии никакое количество вызовов GC.Collect () не будет влиять на LOH, но в вашем случае это, похоже, помогает. Однако, это источник подавляющего большинства исключений OutOfMemory, которые я видел.
Еще одно место, где сборщик мусора не всегда работает хорошо, - это когда некоторые вещи вызывают укоренение объектов. Одним из примеров является то, что обработчики событий могут предотвратить сбор объекта. Чтобы обойти это, убедитесь, что каждая операция +=
для подписки на событие имеет соответствующую операцию -=
для отмены подписки. Но опять же, GC.Collect () вряд ли поможет здесь - объект все еще где-то укоренен и поэтому не может быть собран.
Надеюсь, это даст вам возможность исследовать вашу основную проблему, которая в первую очередь вызывает необходимость использования GC.Collect (). Но если нет, то, конечно, лучше иметь работающую программу, чем неисправную. Везде, где я использую GC.Collect (), я хотел бы убедиться, что код хорошо документирован с указанием причины, по которой он вам нужен (без исключений), а также с точными шагами и данными, необходимыми для его надежного воспроизведения, так что что будущие программисты, которые могут захотеть удалить это, могут точно знать, когда это безопасно.