К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как завершить COM-соединение в 1С

Как корректно завершить COM-соединение в 1С: освобождение COMConnector, обнуление переменных, сборка мусора, зависшие процессы и типичные ошибки.

COM-соединение в 1С (объект V83.COMConnector или V82.COMConnector) открывает отдельный канал между базами и удерживает ресурсы на обеих сторонах: память клиентского процесса, сеанс на сервере 1С и соединение с СУБД. Если соединение не завершить, сеанс в кластере может «зависнуть» до таймаута, а при массовом обмене такие «хвосты» приводят к исчерпанию памяти и блокировкам.

Проблема усугубляется тем, что у COM-соединения в 1С нет метода Close() или Disconnect(). Разработчики привыкли к явному закрытию соединений в других технологиях и ищут аналогичную команду — но механика завершения здесь другая: соединение живёт, пока живы ссылки на него, и закрывается при освобождении объектов и работе сборщика мусора.

Ниже разобраны рабочие способы завершения COM-соединения из кода 1С и из внешних приложений, способы принудительного снятия зависших сеансов и проверка того, что соединение действительно закрыто.

Как устроено завершение COM-соединения и почему нет метода Close()

Объект COMConnector — это COM-обертка, время жизни которой управляется подсчётом ссылок. Пока существует хотя бы одна переменная, ссылающаяся на соединение или на любой объект, полученный через него (например, Соединение.Справочники.Номенклатура), соединение считается активным. Как только последняя ссылка освобождена, COM-объект уничтожается, а сеанс на стороне базы-источника завершается.

Из этого следует главное правило: завершить соединение — значит освободить все ссылки. Присваивание Неопределено переменной соединения недостаточно, если где-то осталась переменная с выборкой, объектом документа или менеджером справочника, полученными через это соединение. Все они удерживают соединение открытым.

Стандартный способ: обнуление переменных и выход из процедуры

Самый надёжный сценарий — локальные переменные внутри процедуры или функции. Когда процедура завершается, локальные переменные уничтожаются, ссылки освобождаются, и COM-соединение закрывается автоматически. Поэтому рекомендуемый шаблон — весь код работы с соединением держать в одной процедуре и не выносить COM-объекты в глобальные переменные или реквизиты формы.

Если переменная объявлена в модуле или соединение нужно закрыть до конца процедуры, присвойте всем связанным переменным значение Неопределено в обратном порядке: сначала объекты данных, потом само соединение, затем коннектор.

bsl
Процедура ОбменДанными()
    Коннектор = Новый COMОбъект("V83.COMConnector");
    Соединение = Коннектор.Connect("Srvr=...;Ref=...;Usr=...;Pwd=...;");
    // работа с данными
    Соединение = Неопределено;
    Коннектор = Неопределено;
КонецПроцедуры

Обратите внимание: обнулять нужно и коннектор, и соединение. Объект COMConnector сам по себе тоже удерживает ресурсы, а при повторных подключениях в цикле неосвобождённые коннекторы накапливаются в памяти клиентского процесса.

Порядок корректного завершения
  1. 1
    Завершите все операции с данными и убедитесь, что транзакции зафиксированы или отменены
  2. 2
    Обнулите переменные с объектами данных, полученными через соединение (выборки, объекты документов, менеджеры)
  3. 3
    Присвойте переменной соединения значение Неопределено
  4. 4
    Присвойте переменной коннектора (COMConnector) значение Неопределено
  5. 5
    При массовых обменах в цикле вызовите сборку мусора или вынесите итерацию в отдельную процедуру
  6. 6
    Проверьте в консоли кластера, что сеанс завершён

Принудительное ускорение: сборка мусора и отдельные процедуры

В файловых базах и толстом клиенте освобождение COM-объектов происходит при разрушении переменных, но платформа может откладывать фактическую очистку. Если в длительной операции открываются десятки соединений подряд, память растёт, хотя переменные обнуляются. В таких случаях помогает вынос итерации обмена в отдельную процедуру: при её завершении движок гарантированно освобождает локальные объекты.

Дополнительный приём — вызов метода ВыполнитьСборкуМусора() (доступен в новых версиях платформы) после обнуления ссылок. Это не гарантирует мгновенного уничтожения COM-объекта, но ускоряет освобождение внутренних структур платформы. Во внешних приложениях на .NET аналогичную роль играют Marshal.ReleaseComObject и GC.Collect().

Завершение соединения из внешних приложений

При подключении к 1С из внешних программ (скрипты PowerShell, приложения на C#, обработчики на VBScript) действуют те же принципы, но с особыми требованиями среды. В .NET COM-объекты оборачиваются в RCW-обертки, которые не освобождаются обычным присваиванием null — требуется Marshal.FinalReleaseComObject для каждого COM-объекта, включая промежуточные.

В скриптах VBScript и PowerShell достаточно присвоить переменным Nothing/$null и дождаться завершения скрипта. Если скрипт работает как служба или планировщик с длительным временем жизни, пересоздавайте коннектор на каждый сеанс обмена и не храните его в статических переменных — иначе сеанс в базе 1С будет висеть постоянно.

Способы завершения по среде

Код 1С, локальные переменные

Достаточно выйти из процедуры. Самый надёжный вариант, дополнительных действий не требуется.

Код 1С, модульные переменные

Нужно обнулить все ссылки вручную, включая объекты данных. Риск утечки выше.

Внешнее приложение .NET

Требуется Marshal.ReleaseComObject/FinalReleaseComObject для каждого COM-объекта и GC.Collect.

Скрипты PowerShell/VBScript

Обнуление переменных и завершение скрипта. При постоянно работающем процессе — пересоздание коннектора.

Как снять зависший сеанс COM-соединения на сервере

Если клиентский процесс завершился аварийно, сеанс на сервере 1С может остаться активным и удерживать соединение с СУБД и лицензию. Такой сеанс виден в консоли кластера серверов 1С: у него тип приложения — COM-соединение, и время бездействия растёт. По умолчанию кластер завершает «спящие» сеансы по таймауту, но ждать не обязательно.

Откройте консоль администрирования серверов 1С, найдите нужный кластер, раздел «Сеансы», отфильтруйте по базе и типу приложения, выделите зависший сеанс и удалите его через контекстное меню. Программно то же самое делается через объекты администрирования V83.ComAdmin или через RAC-утилиту командной строки.

Проверка результата и типичные ошибки

Признак успешного завершения — исчезновение сеанса с типом «COM-соединение» в консоли кластера в течение короткого времени после обнуления переменных. В файловом варианте проверить проще: после закрытия соединения база-источник не должна быть заблокирована, и её монопольный режим доступен.

Если сеанс не закрывается, ищите уцелевшую ссылку. Типичные источники: переменная уровня модуля, реквизит формы или объекта, куда сохранили соединение «на всякий случай»; коллекция (массив, соответствие), содержащая COM-объекты; фоновое задание, которое всё ещё выполняется и держит соединение.

Типичные ошибки
01
Обнуление только переменной соединения, но не объектов данных — соединение продолжает жить через выборку или объект документа
02
Хранение COM-соединения в реквизите формы или глобальной переменной — сеанс висит, пока открыта форма или сеанс пользователя
03
Открытие соединения в цикле без освобождения — накопление сеансов и исчерпание памяти рабочего процесса
04
Попытка вызвать несуществующий метод Close/Disconnect — ошибка выполнения и незакрытое соединение
05
Игнорирование исключений: при ошибке в середине кода ветка обнуления не выполняется — используйте Попытка/Исключение с освобождением в блоке Исключение
Контрольные точки

Как проверить результат

Сеанс в консоли кластера
Норма

Сеанс с типом COM-соединение исчезает вскоре после обнуления переменных

Тревожный признак

Сеанс остаётся активным спустя минуты, время бездействия растёт

Память клиентского процесса
Норма

После цикла обмена потребление памяти возвращается к исходному уровню

Тревожный признак

Память растёт с каждой итерацией и не освобождается

Блокировки базы-источника
Норма

После завершения обмена база доступна для монопольных операций

Тревожный признак

База остаётся занятой зависшим сеансом

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

Правильная архитектура обмена избавляет от большинства проблем. Оборачивайте работу с соединением в конструкцию Попытка...Исключение...КонецПопытки и освобождайте ссылки в обеих ветках — и при успехе, и при ошибке. Не передавайте COM-объекты между процедурами параметрами без необходимости: каждая передача — дополнительная ссылка, которую нужно отслеживать.

Для регулярных обменов рассмотрите альтернативы COM: HTTP-сервисы, веб-сервисы или планы обмена. Они управляют сеансами прозрачнее, лучше масштабируются и не зависят от разрядности и регистрации COM-компонентов. COM-соединение оправдано для разовых миграций и локальных интеграций, где простота важнее управляемости.

Итог

Что важно запомнить

COM-соединение в 1С закрывается не командой, а освобождением всех ссылок: обнулите объекты данных, соединение и коннектор или завершите процедуру. Зависшие сеансы снимайте через консоль кластера, а код обмена оборачивайте в Попытка/Исключение с гарантированным освобождением ссылок.

Частые вопросы о завершении COM-соединения

Почему сеанс остаётся в консоли кластера после обнуления переменных?

Кластер не всегда завершает сеанс мгновенно: он может закрыться по таймауту неактивности. Если сеанс висит дольше нескольких минут и не реагирует — ищите уцелевшую ссылку в коде или снимите сеанс вручную через консоль кластера.

Чем отличается V83.COMConnector от V82.COMConnector при завершении?

Механика завершения одинакова — освобождение ссылок. Различие только в версии подключаемой платформы: коннектор должен соответствовать версии сервера базы-источника, иначе подключение вообще не установится.

Можно ли завершить чужое COM-соединение программно?

Да, через механизмы администрирования кластера: объект V83.ComAdmin или утилита RAC позволяют получить список сеансов и удалить нужный. Для этого требуются права администратора кластера.

Что произойдёт с данными при принудительном снятии сеанса?

Незафиксированная транзакция в базе-источнике будет откачена, данные не пострадают, но обмен прервётся на середине. Если обмен был в критичной точке, потребуется повторная выгрузка.

Нужно ли закрывать соединение, если процедура завершилась ошибкой?

Да, обязательно. Именно поэтому освобождение ссылок размещают в блоке Исключение или в отдельной процедуре-обёртке: иначе каждая ошибка обмена будет оставлять открытый сеанс.