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

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

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

Почему обычные способы сохранения не работают?

Рассмотрим стандартную ситуацию: программист пытается сохранить объект COM-соединения в глобальной переменной модуля управляемого приложения или в параметре сеанса. Однако при попытке использования объекта возникает ошибка. Выясним причину этого поведения. Основная проблема заключается в сериализации. COM-объект — это специфический указатель на область памяти в конкретном процессе (на клиенте или на сервере). Его невозможно передать с сервера на клиент или сохранить в базу данных через ХранилищеЗначений, так как при попытке передачи между контекстами объект «теряется».

В управляемом приложении клиент и сервер — это разные процессы. Глобальные переменные на клиенте не видны на сервере, а серверные вызовы в рамках одного сеанса могут выполняться разными рабочими процессами rphost. Следовательно, нам нужен механизм, который позволит «удержать» объект в памяти сервера.

Решение 1: Использование временного хранилища на сервере

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

Проанализируем пример кода, который позволяет реализовать этот функционал:


Функция ПолучитьСоединение(ПараметрыСоединения) Экспорт
    Если ПараметрыСоединения.АдресВХранилище = "" Тогда
        Возврат СоздатьНовоеСоединение(ПараметрыСоединения);
    Иначе
        Попытка
            Структура = ПолучитьИзВременногоХранилища(ПараметрыСоединения.АдресВХранилище);
            Если ТипЗнч(Структура) = Тип("Структура") Тогда
                Соединение = Структура.Соединение;
                // Простейшая проверка на "живучесть" соединения
                Тест = Соединение.NewObject("Запрос");
                Тест.Текст = "ВЫБРАТЬ 1";
                Возврат Соединение;
            Иначе
                Возврат СоздатьНовоеСоединение(ПараметрыСоединения);
            КонецЕсли;
        Исключение
            Возврат СоздатьНовоеСоединение(ПараметрыСоединения);
        КонецПопытки;
    КонецЕсли;
КонецФункции

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

Важный нюанс: при использовании ПоместитьВоВременноеХранилище необходимо передавать второй параметр — УникальныйИдентификатор. Если привязать хранилище к УИД формы, данные будут автоматически удалены при ее закрытии, что предотвратит утечку памяти на сервере.

Решение 2: Кэширование данных на стороне клиента

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

  1. При открытии формы или изменении ключевого параметра (например, склада или торговой точки) выполняется один серверный вызов.
  2. В этом вызове устанавливается кратковременное COM-соединение.
  3. Запросом из внешней базы извлекаются все необходимые данные (например, актуальный прайс-лист).
  4. Данные возвращаются на форму в виде ДанныеФормыКоллекция (таблицы).
  5. Последующая работа пользователя (подбор товара) происходит мгновенно, так как данные уже находятся «под рукой» и обращения к внешней базе больше не требуются.

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

Технические и лицензионные ограничения

Проанализируем важные аспекты, которые часто упускаются при реализации COM-интеграции:

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

2. Настройка DCOM. Если базы расположены на разных физических серверах, вы неизбежно столкнетесь с ошибкой «Отказ в доступе». Проблема решается через утилиту dcomcnfg на стороне сервера, где установлена целевая база. Необходимо выдать права на удаленный запуск и активацию компоненту V83.COMConnector для учетной записи, под которой работает служба сервера 1С (обычно это USR1CV8).

3. Фоновые задания. Чтобы форма «не зависала» в момент нажатия кнопки или открытия, процедуру СоздатьНовоеСоединение лучше выносить в фоновое задание. Выясним, почему это важно: инициализация COM может занимать от 2 до 10 секунд в зависимости от загрузки сети. Выполняя это в фоне, вы позволяете пользователю продолжать работу с другими реквизитами формы, пока соединение устанавливается.

Сравнение методов: COM против Web-сервисов

Рассмотрим ситуацию, когда у вас есть возможность выбора технологии. Несмотря на то, что COM кажется проще в реализации «здесь и сейчас», у HTTP/Web-сервисов есть ряд неоспоримых преимуществ:

Если же публикация веб-сервисов невозможна (как в случае автора обсуждаемой темы), использование временного хранилища в связке с проверкой «живучести» объекта запросом — это оптимальный технический компромисс для управляемого приложения 1С 8.3.

← На главную