MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Открытый OleDbConnection не дает завершится программу"
Answer 797408
Мне не удалось воспроизвести зависание программы при наличии незакрытого
OleDbConnection
. Впрочем, это не удивительно, похоже, речь идет о неопределенном поведении.Так вот, под конец работы приложения программа зависает, если не вызвать Dispose, хотя... в этом случае должен отработать финализатор.
Все немного сложнее. Класс
OleDbConnection
внутренне использует несколько COM-объектов: объект Data Links, который отвечает за управление пулом соединений - один на домен приложений, и объекты Data Source и Session - по одному на каждое соединение. См. здесь. При ручном закрытии соединения обеспечивается корректный порядок действий:
Сброс данных из внутренних буферов в физическое хранилище
Возврат соединения в пул, или закрытие физического соединения, если пул отключен
По завершении приложения (при выгрузке домена), освобождаются объекты, связанные с физическими соединениями и последним - глобальный объект пула.
Если соединение явно не закрывается, при завершении приложения все объекты кучей попадают в очередь финализации, и выполняется попытка их освободить в специальном потоке. При этом, как сказано в документации, порядок вызова финализаторов не определен. Это нарушает логику работы с БД: если финализатор для глобального объекта пула попадет в очередь до объекта соединения, он будет ждать освобождения соединения и не дождется никогда, возникает взаимоблокировка. Видимо, у вас что-то подобное и происходит.
При работе с соединениями с БД, конечно, не стоит полагаться на финализаторы и нужно явно закрывать соединение, когда оно больше не нужно (в вашем случае, класс Converter должен тоже реализовывать
IDisposable
, и в конце программы для него вызыватьDispose
). Это обеспечивает корректный порядок действий при освобождении ресурсов, завершение выполняющихся в данный момент транзакций и сброс закэшированных данных в место назначения.Закрытие соединение с БД через финализатор никогда не было поддерживаемым режимом, в документации везде это четко написано. Класс
SqlConnection
, к примеру, вообще вызывает в конструктореSuppressFinalize
, так что его финализатор никогда не будет вызван.
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.