Почему я не должен использовать GC.Collect()
Я разрабатываю приложение, в котором я работаю с CertAdm.dll, чтобы установить соединение с центром сертификации. Иногда я получаю сообщение об ошибке: "Была предпринята попытка открыть сеанс базы данных центра сертификации, но активных сеансов уже слишком много. Возможно, необходимо настроить сервер для разрешения дополнительных сеансов".
Если я настраиваю свое соединение как код ниже, я не получаю ошибку, и все работает отлично.
CERTADMINLib.ICertView2 cv2 = new CERTADMINLib.CCertViewClass();
try
{
cv2.OpenConnection(srtCAConfig);
}
catch
{
GC.Collect();
GC.WaitForPendingFinalizers();
cv2.OpenConnection(srtCAConfig);
}
Теперь меня интересует то, что я много читал, где люди говорят, что вы не должны использовать GC.Collect(). Почему я не должен? Это решает мою проблему?
Вся помощь очень ценится.
3 ответа
Краткий ответ: сбор мусора становится менее эффективным, чем больше вы это делаете.
Ожидание ожидающих финализаторов также нежелательно. Вы задерживаете свой код для ожидания неизвестного числа объектов для выполнения операций очистки, которые могут занимать неизвестное количество времени. Если вы исправите основную проблему, вам не нужно будет ждать ни одной из них.
Что касается основной проблемы, когда объект владеет каким-то внешним (дефицитным) ресурсом, важно, чтобы, когда вы закончили с ним, вы вызывали соответствующий метод для освобождения ресурса. Часто это метод с именем Dispose(), CloseConnection() или что-то подобное.
тем не менее, это COM-объект взаимодействия, и все MSDN говорит, что
Чтобы закрыть соединение, вызовите функцию Release (C++) или установите для объекта значение Nothing (Visual Basic).
В.NET эквивалентным является вызов System.Runtime.InteropServices.Marshal.ReleaseComObject(cv2). Как только вы это сделаете, объект, на который ссылается cv2, недействителен, поэтому не вызывайте его снова.
Я думаю, что вы не закрываете соединения после их открытия, и, наконец, оно превышает максимальное количество соединений, которые могут быть открыты одновременно. Когда вы передаете GC.Collect(), каждый раз, когда объект соединения принудительно собирается, из-за чего вы не можете повторно использовать уже открытое соединение.
Возможно, это решит вашу проблему из-за некорректной работы с соединениями в вашем классе.
Попробуйте изучить все соединения в вашем приложении, посмотреть, где они открыты и где закрыты - я думаю, что вы не закрываете соединения / не очищаете ресурсы, которые используются вашими соединениями.