Как правильно закрыть COM-соединение с другой базой в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Механизм управления COM-соединением в 1С

В платформе 1С:Предприятие не предусмотрено явного метода вроде Отключить() или ЗакрытьСоединение(). Физическое завершение сеанса происходит автоматически тогда, когда счетчик ссылок COM-объекта в операционной системе Windows становится равным нулю.

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

  1. Удержание ссылок на объекты удаленной базы: если в коде были получены ссылки на справочники, документы, выборки запросов или таблицы значений внешней базы (например, ВнешнийОбъект = Соединение.Справочники.Номенклатура.НайтиПоКоду("001");) и они не были очищены, сеанс не закроется.
  2. Удержание ссылки на сам коннектор: если переменная, содержащая объект V83.COMConnector, остается в памяти (в глобальном модуле, реквизите формы или модуле сеанса), соединение помещается в системный пул и не разрывается.

Способ 1: Явное обнуление ссылок на объекты и коннектор

Рассмотрим правильный порядок очистки переменных в коде. Присвоение переменной пустой строки "" может приводить к неявным ошибкам приведения типов, поэтому эталонным способом в 1С является присвоение значения Неопределено.

Разберем по шагам правильный алгоритм работы с COM-соединением:

  1. Инициализируем COM-коннектор.
  2. Устанавливаем соединение с базой.
  3. Выполняем необходимые операции, сохраняя результат в простые типы текущей базы (числа, строки, структуры).
  4. Обнуляем все промежуточные COM-объекты.
  5. Обнуляем объект соединения и объект коннектора.

Посмотрим на пример безопасного кода с обработкой исключений:


COMКоннектор = Неопределено;
COMСоединение = Неопределено;
ВыборкаCOM = Неопределено;

Попытка
    COMКоннектор = Новый COMОбъект("V83.COMConnector");
    COMСоединение = COMКоннектор.Connect("Srvr=""Server1C"";Ref=""TargetBase"";Usr=""Admin"";Pwd=""Password"";");
    
    // Выполняем действия в удаленной базе
    Запрос = COMСоединение.NewObject("Запрос");
    Запрос.Текст = "ВЫБРАТЬ Ссылка, Наименование ИЗ Справочник.Номенклатура";
    ВыборкаCOM = Запрос.Выполнить().Выбрать();
    
    Пока ВыборкаCOM.Следующий() Цикл
        // Обработка данных
    КонецЦикла;
Исключение
    ЗаписьЖурналаРегистрации("COM-соединение", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
КонецПопытки;

// Гарантированно освобождаем ресурсы
ВыборкаCOM = Неопределено;
COMСоединение = Неопределено;
COMКоннектор = Неопределено;

Способ 2: Изоляция работы в локальный контекст

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

Посмотрим на пример правильной изоляции контекста:


Функция ПолучитьКурсыВалютИзБазы(ПараметрыПодключения) Экспорт
    Результат = Новый ТаблицаЗначений;
    
    Коннектор = Новый COMОбъект("V83.COMConnector");
    Соединение = Коннектор.Connect(ПараметрыПодключения);
    
    // Получаем данные и переносим их в локальную таблицу значений
    // Избегаем возврата наружу прямых COM-объектов
    
    // При выходе из функции локальные переменные Коннектор и Соединение 
    // будут очищены платформой автоматически
    Возврат Результат;
КонецФункции

Специфика работы через COM+ и процесс dllhost.exe

Если для обхода разрядности (например, подключение из 64-битного сервера 1С к 32-битному COM-коннектору) используется серверное приложение COM+ в Windows, процесс dllhost.exe может удерживать соединение даже после обнуления всех переменных в коде 1С.

В этом случае сеанс закрывается только по истечении таймаута неактивности (Idle Timeout), настроенного в свойствах приложения в оснастке «Службы компонентов» (Component Services). Для минимизации простоя лицензий рекомендуется уменьшить время отключения приложения при простое до 1–2 минут.

Принудительное завершение сеанса средствами администрирования

Если требуется гарантированно и мгновенно разорвать сеанс на стороне целевой базы, можно воспользоваться административными инструментами платформы:

  1. Использовать объект V83.COMAdmin и вызвать метод TerminateSession() у соответствующего кластера серверов.
  2. Выполнить команду отключения сеанса через консольную утилиту rac, взаимодействующую со службой ras целевого кластера.

Ограничения технологии и рекомендуемые альтернативы

COM-соединение имеет существенные архитектурные ограничения:

  1. Привязка к ОС Windows: библиотека comcntr.dll не работает на серверах под управлением Linux.
  2. Чувствительность к версиям: прямое подключение невозможно между базами, работающими на существенно разных релизах платформы, без сложной настройки псевдонимов в реестре.
  3. Утечки лицензий: зависшие сеансы блокируют клиентские лицензии 1С.

Для современной и стабильной межсистемной интеграции рекомендуется заменять COM-соединения на:

  1. HTTP-сервисы и REST API (включая OData): сеанс открывается исключительно на время выполнения HTTP-запроса и сразу закрывается, не создавая блокировок.
  2. Web-сервисы (SOAP): стандартный механизм для синхронного вызова процедур с жесткой типизацией.
  3. Брокеры сообщений (RabbitMQ, Apache Kafka): надежный асинхронный обмен с гарантией доставки данных.
← На главную