Как программно назначить событие onComm для библиотеки MSCOMM32.ocx в 1С

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

При работе с внешним оборудованием через COM-порты (RS-232) программисты 1С часто сталкиваются с необходимостью использовать библиотеку MSCOMM32.ocx. Если при визуальном проектировании на обычных формах (ActiveX) проблем с назначением событий не возникает, то при динамическом создании объектов в коде процедура связки события с обработчиком становится не столь очевидной. Разберем подробно, как реализовать событийную модель получения данных из порта, чтобы избежать ненадежных методов вроде постоянного опроса буфера по таймеру.

Проблема использования обработчика ожидания

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

  1. Отсутствие синхронизации: Вы можете обратиться к буферу слишком рано (когда данные еще не пришли целиком) или слишком поздно.
  2. Разрыв строк: При чтении по таймеру высока вероятность получить «обрывки» сообщений, что требует сложной логики склейки пакетов данных.
  3. Нагрузка на систему: Постоянный опрос порта в основном потоке интерфейса может приводить к микрофризам программы.

Событийная модель, предоставляемая библиотекой через onComm, работает оптимально: как только в буфер поступает заданное количество байт, генерируется прерывание, и 1С мгновенно вызывает нужную процедуру.

Использование функции ДобавитьОбработчик

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

Сначала создадим сам объект и настроим его параметры. Обратите внимание на свойство RThreshold — именно оно определяет, при каком количестве байт в приемном буфере возникнет событие onComm.


// Создаем объект динамически
ComPort = Новый COMОбъект("MSCOMMLib.MSComm.1");

// Настраиваем параметры подключения
ComPort.CommPort = 9; // Номер порта
ComPort.Settings = "9600,N,8,1"; // Скорость, четность, биты данных, стоп-биты
ComPort.RThreshold = 1; // Событие onComm возникнет при получении хотя бы 1 байта
ComPort.InputLen = 0; // Считывать весь буфер целиком при вызове Input
ComPort.PortOpen = Истина;

// Назначаем обработчик события onComm
// Синтаксис: ДобавитьОбработчик Объект.Событие, НазваниеПроцедуры
ДобавитьОбработчик ComPort.onComm, ОбработкаСобытияOnComm;

Важный нюанс: процедура-обработчик должна находиться в том же модуле, где вызывается ДобавитьОбработчик, и быть доступной для вызова. Если вы работаете в модуле формы, процедура должна быть объявлена без ключевого слова Экспорт (или с ним, если это необходимо по архитектуре).

Реализация процедуры обработки данных

Теперь рассмотрим, как должна выглядеть сама процедура, принимающая данные от устройства. Проанализируем состояние свойства CommEvent, которое указывает на причину возникновения события.


Процедура ОбработкаСобытияOnComm()
    // Проверяем, что событие вызвано именно приходом данных (код 2)
    Если ComPort.CommEvent = 2 Тогда
        ДанныеИзПорта = ComPort.Input;
        // Здесь размещаем логику обработки полученной строки
        Сообщить("Получены данные: " + ДанныеИзПорта);
    КонецЕсли;
КонецПроцедуры

Важный момент: Свойство InputMode определяет формат данных. Если вы работаете с текстовыми данными, оставьте значение 0 (текст). Если устройство присылает бинарные данные (байты), установите ComPort.InputMode = 1.

Технические нюансы и возможные проблемы

При использовании MSCOMM32.ocx и функции ДобавитьОбработчик следует учитывать несколько важных факторов, которые могут повлиять на стабильность системы:

  1. Разрядность клиента: Библиотека MSCOMM32 является 32-битной. Она будет корректно работать только в 32-битном клиенте 1С. В 64-битном приложении создание этого COM-объекта завершится ошибкой.
  2. Стабильность потоков: Как отмечают опытные разработчики, прямое связывание событий через ДобавитьОбработчик для высокоинтенсивных потоков данных может иногда приводить к аварийному завершению работы платформы 1С. Это связано с тем, что COM-объект генерирует событие в своем потоке, а 1С должна корректно «пробросить» его в контекст выполнения скрипта.
  3. Лицензирование ActiveX: На некоторых компьютерах может возникнуть ошибка «Лицензия не найдена». Это особенность старых компонентов Microsoft. Для решения требуется внесение соответствующего runtime-ключа в реестр Windows по пути HKEY_CLASSES_ROOT\Licenses.

Альтернативный путь: Внешние компоненты (ВК)

Если в процессе эксплуатации вы заметите нестабильность (падения платформы), рассмотрим вариант использования специализированных внешних компонент. Внешняя компонента, написанная по технологии Native API, взаимодействует с 1С через метод ВнешнееСобытие. В этом случае данные попадают в стандартную очередь событий 1С, что является наиболее безопасным и «правильным» способом с точки зрения архитектуры платформы.

Однако, для простых задач или при наличии уже отлаженного кода на MSCOMM32, использование ДобавитьОбработчик является самым быстрым и эффективным способом реализовать полноценный обмен данными с оборудованием без лишних «костылей» в виде таймеров.

Резюмируем: Для программного назначения события используем ДобавитьОбработчик, не забываем устанавливать RThreshold больше нуля и обязательно проверяем код события CommEvent внутри обработчика, так как onComm может срабатывать не только на приход данных, но и на ошибки линии или изменение сигналов квитирования (CTS/DSR).

← На главную