Как сохранить COM-объект между серверными вызовами в управляемых формах 1С?

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

При разработке интеграционных механизмов в управляемом приложении 1С программисты часто сталкиваются с задачей сохранения установленного внешнего COM-соединения (например, через V83.COMConnector) между несколькими несвязанными серверными вызовами. Повторная инициализация соединения при каждом нажатии кнопки или обработке порции данных требует значительных накладных расходов по времени.

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

Почему возникают ошибки при сохранении COM-объекта?

Проанализируем ситуацию: платформа 1С разделяет контекст выполнения на клиентский и серверный уровни. Это накладывает строгие ограничения на типы данных:

  1. Реквизиты формы: тип COMОбъект не может использоваться в качестве типа данных формы, поскольку данные формы должны сериализоваться для передачи между сервером и клиентом. При попытке присвоения возникает исключение: «Тип "COMОбъект" не может использоваться в данных формы».
  2. Передача между клиентом и сервером: COM-объект является указателем в оперативной памяти конкретного процесса Windows. Попытка объявить клиентскую переменную &НаКлиенте Перем V8; и передать ее параметром в серверную процедуру вызывает ошибку сериализации XDTO: «Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа».
  3. Прямое помещение во временное хранилище: прямой вызов ПоместитьВоВременноеХранилище(COMОбъект, УникальныйИдентификатор) завершается ошибкой, так как платформа требует сериализуемый объект верхнего уровня.

Способ 1. Сохранение COM-объекта через структуру во временном хранилище

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

Посмотрим на пример инициализации и сохранения адреса хранилища в строковый реквизит объекта или формы:


&НаСервере
Процедура ИнициализироватьСоединениеНаСервере()
    
    COMКоннектор = Новый COMОбъект("V83.COMConnector");
    УстановленноеСоединение = COMКоннектор.Connect(СтрокаПодключения);
    
    // Оборачиваем COM-объект в структуру
    Контейнер = Новый Структура("COMСоединение", УстановленноеСоединение);
    
    // Сохраняем адрес хранилища в строковый реквизит формы
    АдресХранилищаCOM = ПоместитьВоВременноеХранилище(Контейнер, УникальныйИдентификатор);
    
КонецПроцедуры

Рассмотрим, как получить ранее сохраненное соединение в последующих несвязанных серверных процедурах:


&НаСервере
Процедура ВыполнитьОперациюНаСервере()
    
    Если Не ЗначениеЗаполнено(АдресХранилищаCOM) Тогда
        Возврат;
    КонецЕсли;
    
    // Извлекаем контейнер из временного хранилища
    Контейнер = ПолучитьИзВременногоХранилища(АдресХранилищаCOM);
    
    Если Контейнер <> Неопределено И Контейнер.Свойство("COMСоединение") Тогда
        V8 = Контейнер.COMСоединение;
        
        // Выполняем действия в подключенной базе
        РезультатЗапроса = V8.NewObject("Запрос");
        // ... работа с базой
    КонецЕсли;
    
КонецПроцедуры

Способ 2. Использование общего модуля с повторным использованием возвращаемых значений

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

Разберем реализацию функции внутри такого модуля:


// В общем модуле с повторным использованием "На время сеанса"
Функция ПолучитьКэшированноеCOMСоединение(СтрокаПодключения) Экспорт
    
    COMКоннектор = Новый COMОбъект("V83.COMConnector");
    Соединение = COMКоннектор.Connect(СтрокаПодключения);
    
    // Кэшируем внутри структуры или соответствия
    Результат = Новый Структура("Подключение", Соединение);
    
    Возврат Результат;
    
КонецФункции

Рассмотрим особенности этого метода:

  1. Кэш модуля сбрасывается платформой автоматически через 20 минут неактивности либо принудительно через вызов ОсвежитьПовторноИспользуемыеЗначения().
  2. Способ требует изменения конфигурации (добавления общего модуля), что не всегда применимо при разработке внешних отчетов и обработок.

Важные ограничения и риски сохранения COM-объектов на сервере

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

  1. Многопроцессный кластер серверов: COM-объект привязан к адресному пространству конкретного рабочего процесса rphost. Если кластер серверов балансирует нагрузку и перенаправит следующий серверный вызов клиента на другой рабочий процесс или другой сервер, попытка прочитать COM-указатель из временного хранилища приведет к ошибке.
  2. Зависание лицензий: активный экземпляр V83.COMConnector удерживает клиентскую лицензию в подключаемой базе на все время своего существования. Длительное хранение объекта в памяти расходует пул доступных лицензий.
  3. Освобождение памяти: неуправляемые ресурсы COM требуют явного уничтожения. Рекомендуется после завершения работы всегда занулять ссылку: V8 = Неопределено;.
  4. Несовместимость с серверами на Linux: COM-технология работает исключительно в операционных системах семейства Windows. На серверах 1С под управлением Linux данный код выполняться не сможет.

Рекомендуемые альтернативы

Если требуется надежная архитектура обмена данными между базами 1С, рекомендуется использовать современные платформенные механизмы:

  1. Фоновые задания: выносите пакетную обработку в фоновое задание через ФоновыеЗадания.Выполнить(). Вся работа с COM-коннектором от подключения до закрытия выполняется в рамках одного процесса без разрыва контекста.
  2. HTTP-сервисы и Web-сервисы: разработка REST API на стороне целевой базы через HTTPСервисы. Такие запросы выполняются по стандарту без сохранения состояния (stateless), одинаково работают на Windows и Linux и не зависят от процессов кластера.
  3. Интерфейс OData: использование стандартного REST-интерфейса OData, который активируется штатно в конфигурации без написания дополнительного кода.
← На главную