Обнаружение, если сборщик "мусора" был вызван (.NET)

При использовании SqlConnection важно всегда закрыть его при использовании - любой.Close () или размещение SqlConnection в "использовании". Unfurtunately, люди, включая меня, склоняются к, забыл, что и это - то, где сборщики "мусора" спасают меня некоторое время, пока я не имею, забыл закрывать мои соединения слишком много раз, или число людей, использующих приложение, растет.

Я хотел бы знать, если даже возможно, как обнаружить, если сборщик "мусора" расположил SqlConnection, потому что он полагал, что он больше не использовался или если SqlConnection был закрыт корректный путь.

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

Возможно, существует одна треть и еще более умный путь ко всему этому... Что Вы порекомендуете?

5
задан Jan Sommer 29 June 2010 в 18:17
поделиться

6 ответов

Поскольку SqlConnection запечатан, вы не сможете наследовать от него. (И я не думаю, что это хорошая идея - если бы это было возможно, вам, вероятно, следует добавить свой код в Dispose (false), потому что это то, что вызывает финализатор).

Лучше обнаруживать подобные проблемы с помощью инструмента статического анализа кода, который может обнаружить все места в вашем коде, где вы забыли удалить соединение. Он встроен в в Visual Studio , или вы можете использовать FxCop .

Чтобы помочь вам не забыть об удалении соединения, рекомендуется:

  • Хранить весь код соединения с БД на одном уровне / сборке / модуле, чтобы он не разбрасывался по проектам.
  • Имеются служебные методы для выполнения команд SQL и возврата результатов; поэтому вы не создаете SQLConnection больше мест, чем вам нужно.
  • Не забудьте использовать C # using конструкция .
4
ответ дан 14 December 2019 в 04:29
поделиться

Одно практическое правило гласит: «Если вам нужно подумать о сборщике мусора, вы, вероятно, делаете что-то не так». (Конечно, есть и другие недостатки ...)

Мне кажется, что обеспечение закрытия соединений явно или через с использованием блоков и finally - лучший путь.

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

2
ответ дан 14 December 2019 в 04:29
поделиться

Я не очень хорошо знаком со сборщиком мусора и не знаю, есть ли прямой способ получить информацию, но моя первая идея заключается в следующем.

Просто создайте слабую ссылку на фиктивный объект. Если вы позже посмотрите на слабую ссылку и объект больше не жив , вы, вероятно, можете предположить, что произошла сборка мусора.

(Этот ответ относится только к обнаружению запусков сборщика мусора. Я полностью проигнорировал причину этого - есть гораздо более эффективные стратегии борьбы с утечками ресурсов.)

1
ответ дан 14 December 2019 в 04:29
поделиться

Если ваше приложение использует пул подключений SQL (по умолчанию), оно будет не имеет значения, поскольку соединения используются повторно и не закрываются при вызове .Close () или выходе из блока using () {}.

http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx

Чтобы ответить на ваш вопрос, я не верю, что есть событие для сбора сборщика мусора, однако это не имело бы значения, если бы оно было, потому что вы никогда не узнаете, решил ли GC повторно использовать ваш объект на этом этапе сбора (не все объекты очищаются из-за алгоритма генерации).

Я бы также избегал попыток использовать таймеры и «проверки», поскольку вы, скорее всего, будете содержать ссылки на объект и предотвратить его удаление.

1
ответ дан 14 December 2019 в 04:29
поделиться

Во-первых, если вы даже подумываете об использовании GC, у вас где-то есть серьезные проблемы. Я полагаю, что лучший способ гарантировать, что ваш код вызывает Close, - это модульное тестирование вашего кода с использованием таких приемов, как mocking . Если ваш модульный тест показывает, что Close был вызван, ваш код правильный, и вам не нужно делать что-либо излишне опасное, например, возиться с помощью сборщика мусора.

Во-вторых, если вы по-прежнему настаиваете на проверке во время выполнения, то единственное , которое вам следует даже подумать, - это перехват события StateChange для SqlConnection . Это сработает, если, например, ConnectionState изменится с Open на Closed.

0
ответ дан 14 December 2019 в 04:29
поделиться

Если вы забудете удалить объект, объект будет завершен. Невозможно контролировать время, в которое это происходит, и вы также не можете узнать, завершен ли объект. Для финализации объектов необходимо создать отдельный поток, чтобы замедлить работу вашего приложения. Вот почему вы хотите избавиться. Во всех классах фреймворка, реализующих IDisposable, выполняется вызов GC.SuppressFinalize, поэтому объект не финализируется.

Вы не можете контролировать такое поведение. Если ваш объект больше не используется, он будет автоматически собран. Все, что вы можете сделать, чтобы остановить это, - это вызвать GC.SuppressFinalize, но я бы не рекомендовал этого, потому что, если вы потом забудете, вы будете облажались на всю жизнь.

Однако вы можете создать класс-оболочку (не дочерний класс), который вы используете в своем коде, который предоставляет несколько простых методов, которые всегда вызывают Dispose. В противном случае просто проверьте очень хорошо.

0
ответ дан 14 December 2019 в 04:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: