Почему возникает ошибка «Обработчик события не найден» при подписке на событие ПередЗаписью и как её исправить?

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

Разработка и доработка типовых конфигураций на платформе 1С:Предприятие 8.3 иногда преподносят неожиданные сюрпризы при переходе между клиентским и серверным контекстами. Типичная ситуация: в клиентском обработчике формы вызывается серверная процедура, внутри которой создается или модифицируется объект прикладного решения (например, ДокументОбъект). Однако при попытке перехода в серверный метод или в момент вызова метода Записать() платформа аварийно завершает работу с исключением вида: «При подписке ... на событие ПередЗаписью произошла ошибка. Обработчик события не найден».

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

Анализируем механизм возникновения проблемы

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

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

Способ 1. Переключение запуска на тонкий клиент

Большинство современных типовых решений (таких как «Управление торговлей», «ERP Управление предприятием», «Комплексная автоматизация») спроектированы строго под работу в тонком клиенте или веб-клиенте. Запуск таких систем в режиме толстого клиента управляемого приложения часто приводит к конфликтам доступности контекстов.

Разберем по шагам, как принудительно задать режим тонкого клиента:

  1. Откроем стартовое окно запуска информационных баз 1С:Предприятия.
  2. Выделим нужную информационную базу и нажмем кнопку Изменить.
  3. На последней вкладке параметров информационной базы найдем параметр Основной режим запуска.
  4. Переключим значение с Толстый клиент на Тонкий клиент (или установим вариант Выбирать автоматически).
  5. Если запуск выполняется через командную строку или ярлык, проверим параметры запуска на наличие ключа /RunModeThickClient и заменим его на ключ /RunModeThinClient.

После запуска сеанса в тонком клиенте объектная модель не будет компилироваться на клиенте, и вызов серверной процедуры с созданием документа отработает штатно.

Способ 2. Очистка кэша и устранение последствий динамического обновления

Если ошибка возникает спонтанно в типовом коде или после обновления конфигурации, первоочередной причиной выступает повреждение кэша метаданных. Выполним регламентные действия по очистке и перекомпиляции метаданных:

  1. Завершим все активные пользовательские сеансы и закроем конфигуратор.
  2. Выполним очистку локального кэша платформы на рабочем месте разработчика. Для этого удалим содержимое каталогов временных файлов 1С в профиле пользователя:
    
    %LocalAppData%\1C\1cv8\
    %AppData%\1C\1cv8\
    
  3. Если используется клиент-серверный вариант работы, перезапустим службу кластера серверов 1C:Enterprise 8.3 Server Agent для сброса серверного кэша.
  4. Откроем конфигуратор в монопольном режиме и выполним команду меню Конфигурация — Обновить конфигурацию базы данных (горячая клавиша F7). При необходимости выполним сравнение и объединение с эталонным файлом поставки конфигурации для восстановления корректных связей метаданных.
  5. Выполним тестирование и исправление информационной базы через меню Администрирование — Тестирование и исправление с установленной галкой Реструктуризация таблиц информационной базы.

Способ 3. Проверка свойств модуля и директив компиляции

Посмотрим на свойства общего модуля, содержащего обработчик подписки. Если подписка привязана к модулю, доступному только на сервере, но контекст ее вызова по какой-то причине требует клиентской доступности, нельзя просто бездумно ставить флаг Клиент (управляемое приложение). Это повлечет за собой необходимость оборачивать весь неклиентский код директивами препроцессора.

Вместо этого проанализируем следующие параметры модуля:

  1. Убедимся, что процедура-обработчик объявлена с ключевым словом Экспорт:
    
    Процедура ОбработкаПередЗаписьюДокумента(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
        // Код логики подписки
    КонецПроцедуры
    
  2. Проверим, не обернут ли метод обработчика в директивы условной компиляции, которые исключают его компиляцию на сервере, например:
    
    #Если Сервер Тогда
        // Обработчик должен быть доступен здесь
    #КонецЕсли
    
  3. Если из клиентского кода требуется прямой вызов экспортного метода общего модуля (не обработчика подписки, а вспомогательной функции), у модуля должен быть взведен признак Вызов сервера при активном свойстве Сервер. При этом флаг Клиент (управляемое приложение) модулю не требуется.

Стандарты разработки для толстого клиента

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


#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

// Основной исполняемый код модуля объекта

#Иначе
    ВызватьИсключение НСтр("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли

Такая конструкция предотвращает выполнение серверных алгоритмов в неподдерживаемом клиентском окружении и локализует ошибки на этапе компиляции.

← На главную