При разработке внешних компонент по технологии Native API для платформы 1С:Предприятие разработчики часто сталкиваются с ситуацией, когда функции и методы компоненты успешно вызываются, параметры передаются, метод ExternalEvent возвращает успешный статус, однако в форме 1С обработчик внешнего события не реагирует. Разберем основные причины такого поведения и пошагово рассмотрим правильную реализацию взаимодействия компоненты и управляемой формы.
Наиболее частая ошибка заключается в создании объекта компоненты внутри локальной процедуры (например, при нажатии кнопки или инициализации). Если переменная, содержащая экземпляр внешней компоненты, объявлена локально, то после завершения работы процедуры 1С освобождает ссылку. В этот момент происходит уничтожение объекта (вызов деструктора в C++), и генерация асинхронных событий становится невозможной либо они сбрасываются платформой.
Для того чтобы объект компоненты непрерывно функционировал и мог передавать события в форму, его необходимо сохранять в переменной модуля управляемой формы на клиенте. Объект должен существовать все время, пока форма открыта и ожидает событий.
Посмотрим на правильный шаблон работы с Native-компонентой в модуле управляемой формы:
&НаКлиенте
Перем ОбъектВК;
&НаКлиенте
Процедура Старт(Команда)
ИмяМакета = "ОбщийМакет.ТестВК";
// Подключаем внешнюю компоненту из макета
Если НЕ ПодключитьВнешнююКомпоненту(ИмяМакета, "DemoLib", ТипВнешнейКомпоненты.Native) Тогда
УстановитьВнешнююКомпоненту(ИмяМакета);
ПодключитьВнешнююКомпоненту(ИмяМакета, "DemoLib", ТипВнешнейКомпоненты.Native);
КонецЕсли;
// Создаем экземпляр в переменной модуля
ОбъектВК = Новый("AddIn.DemoLib.Пример");
ОбъектВК.Старт(); // Запуск генерации событий в компоненте
КонецПроцедуры
&НаКлиенте
Процедура Стоп(Команда)
Если ОбъектВК <> Неопределено Тогда
ОбъектВК.Стоп();
ОбъектВК = Неопределено;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ВнешнееСобытие(Источник, Событие, Данные)
// Обработка данных от внешней компоненты
Состояние("Событие: " + Событие + ", Данные: " + Данные);
КонецПроцедуры
Объявления процедуры ВнешнееСобытие(Источник, Событие, Данные) в коде модуля формы недостаточно. Платформа 1С должна знать, что данная процедура назначена обработчиком события формы.
Подключить обработку можно двумя путями:
ВнешнееСобытие и выберем созданную клиентскую процедуру-обработчик.Рассмотрим пример программной подписки на событие:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ДобавитьОбработчик ЭтаФорма.ВнешнееСобытие, ВнешнееСобытие;
КонецПроцедуры
По умолчанию глубина очереди событий в 1С равна единице. Если внешняя компонента генерирует события пакетами или с высокой частотой, а основной поток 1С не успевает их обрабатывать, новые события могут теряться платформой.
Для предотвращения потерь сообщений на стороне внешней компоненты перед отправкой данных рекомендуется настроить размер очереди с помощью метода интерфейса IAddInDefBase:
m_iConnect->SetEventBufferDepth(4000);
Увеличение глубины буфера позволяет гарантировать, что все пачки событий будут сохранены в очереди и последовательно переданы в обработчик формы.
Проанализируем дополнительные нюансы архитектуры управляемого приложения, которые могут препятствовать вызову обработчика:
ExternalEvent доставляются только в то окно (форму), которое в текущий момент является активным. Если пользователь переключился на другую вкладку или окно свернуто, событие не будет перехвачено обработчиком формы. Для глобального перехвата событий можно использовать процедуру ОбработкаВнешнегоСобытия в модуле управляемого приложения.ExternalEvent ожидает строки в кодировке UTF-16 (двухбайтовые символы). На платформах Linux стандартный wchar_t имеет размер 4 байта, поэтому для корректной передачи строк необходимо использовать тип char16_t.