Почему вылетает фоновое задание при чтении XML или получении объекта и как это исправить?

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

Разберем распространенную и коварную проблему при разработке серверных механизмов обмена данными: при выполнении методов СериализаторXDTO.ПрочитатьXML() или Ссылка.ПолучитьОбъект() фоновое задание мгновенно падает. При этом стандартная конструкция Попытка ... Исключение не срабатывает, сеанс аварийно прерывается, а весь процесс обмена останавливается.

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

Выясним причину: почему Попытка — Исключение не ловит ошибку

В платформе 1С компиляция модулей объектов выполняется по принципу «ленивой» (отложенной) загрузки. Исходный код модуля компилируется сервером в исполняемый байт-код не в момент старта системы, а только тогда, когда в памяти физически создается первый экземпляр объекта. Это происходит при вызовах СоздатьЭлемент(), Ссылка.ПолучитьОбъект(), а также при десериализации через СериализаторXDTO.ПрочитатьXML(), когда платформа восстанавливает тип СправочникОбъект.

Если в коде модуля объекта присутствует вызов клиентских процедур (например, Предупреждение(), ОткрытьФорму() и т. п.), сервер на этапе компиляции выдает синтаксическую ошибку: «Процедура или функция с указанным именем не определена».

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

Ограничения платформы, о которых важно помнить

Рассмотрим популярные заблуждения, с которыми сталкиваются разработчики при попытке обойти этот сбой:

  1. Установка флага ОбменДанными.Загрузка = Истина не помогает. Данный флаг предназначен для отключения прикладных проверок и событий (таких как ПередЗаписью или ПриЗаписи). Однако компиляция модуля происходит в момент инициализации объекта в памяти еще до того, как управление дойдет до установки этого свойства.
  2. Нельзя создать объект в обход модуля. Средствами встроенного языка платформы невозможно инстанцировать прикладной объект метаданных (СправочникОбъект, ДокументОбъект) без компиляции его модуля на стороне сервера.

Способ 1. Исправление кода через проверку конфигурации и директивы препроцессора

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

  1. Запустим Конфигуратор и выполним синтаксическую проверку: откроем меню Конфигурация → Проверка конфигурации.
  2. В открывшемся окне обязательно установим флаг «Сервер» и нажмем «Выполнить». Платформа проверит все модули на наличие клиентских методов и выведет список проблемных мест.
  3. Найдем вызовы клиентских процедур (например, Предупреждение()) в модулях объектов и обернем их в директивы препроцессора:
    
    #Если Клиент Тогда
        Предупреждение("Сообщение для пользователя");
    #КонецЕсли
    
    Если этот код вовсе не должен исполняться при серверной работе, правильнее перенести диалоговые интерфейсные функции в модуль формы или модуль команды.
  4. Чтобы исключить появление подобных ошибок в будущем, настроим автоматическую проверку: перейдем в Сервис → Параметры → Модули → Проверка и включим проверку для серверного контекста.

Способ 2. Исправление через расширение конфигурации (без изменения типовой конфигурации)

Если база данных находится на типовой поддержке и прямое редактирование модулей запрещено, воспользуемся механизмом расширений:

  1. Создадим или откроем расширение конфигурации.
  2. Добавим в расширение проблемный справочник или документ.
  3. Переопределим процедуру, содержащую некорректный вызов, с помощью аннотации &Вместо, исключив вызов клиентских модальных методов или обернув его директивой препроцессора.

Способ 3. Чтение данных без создания прикладных объектов (ФабрикаXDTO или ЧтениеXML)

Если цель фонового задания — прочитать данные из файла обмена и обойти падение при десериализации, рассмотрим альтернативные инструменты чтения XML, которые не компилируют модуль объекта:

  1. Использование ФабрикаXDTO.ПрочитатьXML вместо СериализаторXDTO. В отличие от СериализаторXDTO, который пытается напрямую создать прикладной тип 1С (вызывая загрузку модуля), ФабрикаXDTO десериализует данные в универсальный тип ОбъектXDTO. Модуль объекта метаданных при этом не задействуется, и ошибка компиляции не возникает. Из объекта XDTO можно вручную получить значения реквизитов и табличных частей.
  2. Использование объектов ЧтениеXML или ДокументDOM. Потоковый или объектный парсинг XML-документа работает исключительно со строковыми узлами и атрибутами без обращения к контексту метаданных, что гарантирует стабильность выполнения фонового потока.

Способ 4. Изоляция аварийных сбоев через дочерние фоновые задания

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

  1. Вынесем вызов СериализаторXDTO.ПрочитатьXML() или обработку отдельного проблемного элемента в дочернее фоновое задание с помощью метода ФоновыеЗадания.Выполнить().
  2. В основном потоке ожидаем завершения выполнения задания методом ФоновыеЗадания.ОжидатьЗавершения().
  3. Проанализируем свойство Состояние полученного задания. Если возникла ошибка компиляции, аварийно завершится только дочерний сеанс (состояние СостояниеФоновогоЗадания.АварийноЗавершено).
  4. Основной процесс обмена останется работоспособным: зафиксируем ошибку по проблемному элементу в журнале регистрации, пропустим его и продолжим цикл обработки следующих данных.
← На главную