Почему не срабатывает внешнее событие из внешней компоненты Native в 1С?

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

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

1. Время жизни объекта внешней компоненты (основная причина)

Наиболее частая ошибка заключается в создании объекта компоненты внутри локальной процедуры (например, при нажатии кнопки или инициализации). Если переменная, содержащая экземпляр внешней компоненты, объявлена локально, то после завершения работы процедуры 1С освобождает ссылку. В этот момент происходит уничтожение объекта (вызов деструктора в C++), и генерация асинхронных событий становится невозможной либо они сбрасываются платформой.

Для того чтобы объект компоненты непрерывно функционировал и мог передавать события в форму, его необходимо сохранять в переменной модуля управляемой формы на клиенте. Объект должен существовать все время, пока форма открыта и ожидает событий.

Посмотрим на правильный шаблон работы с Native-компонентой в модуле управляемой формы:


&НаКлиенте
Перем ОбъектВК;

&НаКлиенте
Процедура Старт(Команда)
    ИмяМакета = "ОбщийМакет.ТестВК";
    
    // Подключаем внешнюю компоненту из макета
    Если НЕ ПодключитьВнешнююКомпоненту(ИмяМакета, "DemoLib", ТипВнешнейКомпоненты.Native) Тогда
        УстановитьВнешнююКомпоненту(ИмяМакета);
        ПодключитьВнешнююКомпоненту(ИмяМакета, "DemoLib", ТипВнешнейКомпоненты.Native);
    КонецЕсли;
    
    // Создаем экземпляр в переменной модуля
    ОбъектВК = Новый("AddIn.DemoLib.Пример");    
    ОбъектВК.Старт(); // Запуск генерации событий в компоненте
КонецПроцедуры

&НаКлиенте
Процедура Стоп(Команда)
    Если ОбъектВК <> Неопределено Тогда
        ОбъектВК.Стоп();
        ОбъектВК = Неопределено;
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)     
    // Обработка данных от внешней компоненты
    Состояние("Событие: " + Событие + ", Данные: " + Данные);
КонецПроцедуры

2. Привязка обработчика события к форме

Объявления процедуры ВнешнееСобытие(Источник, Событие, Данные) в коде модуля формы недостаточно. Платформа 1С должна знать, что данная процедура назначена обработчиком события формы.

Подключить обработку можно двумя путями:

  1. Через свойства формы в конфигураторе: выделим корень формы, перейдем в окно «Свойства», найдем событие ВнешнееСобытие и выберем созданную клиентскую процедуру-обработчик.
  2. Программно в коде: используем специальную инструкцию платформы при инициализации формы.

Рассмотрим пример программной подписки на событие:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    ДобавитьОбработчик ЭтаФорма.ВнешнееСобытие, ВнешнееСобытие;
КонецПроцедуры

3. Настройка глубины буфера событий

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

Для предотвращения потерь сообщений на стороне внешней компоненты перед отправкой данных рекомендуется настроить размер очереди с помощью метода интерфейса IAddInDefBase:

m_iConnect->SetEventBufferDepth(4000);

Увеличение глубины буфера позволяет гарантировать, что все пачки событий будут сохранены в очереди и последовательно переданы в обработчик формы.

4. Особенности доставки событий в платформе 1С

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

  1. Активность окна формы: события из очереди ExternalEvent доставляются только в то окно (форму), которое в текущий момент является активным. Если пользователь переключился на другую вкладку или окно свернуто, событие не будет перехвачено обработчиком формы. Для глобального перехвата событий можно использовать процедуру ОбработкаВнешнегоСобытия в модуле управляемого приложения.
  2. Блокировка GUI-потока: диспетчеризация очереди событий происходит в основном потоке интерфейса. Если на клиенте выполняется длительный синхронный код или открыто модальное диалоговое окно, вызов обработчика откладывается до завершения блокирующей операции.
  3. Формат строк в Native API: функция ExternalEvent ожидает строки в кодировке UTF-16 (двухбайтовые символы). На платформах Linux стандартный wchar_t имеет размер 4 байта, поэтому для корректной передачи строк необходимо использовать тип char16_t.
← На главную