Как вывести сообщения пользователю из фонового задания в 1С?

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

При разработке длительных операций в 1С (например, формирование тяжелых отчетов или проведение документов) мы часто используем фоновые задания — для этого подойдёт инструментарий разработчика для управления фоновыми заданиями в 1С. Это позволяет не блокировать интерфейс пользователя. Однако возникает проблема: фоновое задание выполняется на сервере в отдельном сеансе, и простые методы вывода информации, такие как Сообщить(), не отображаются на экране пользователя автоматически.

В этой статье мы подробно разберем, как "доставить" сообщения из "фона" на клиент, рассмотрим стандартные механизмы платформы, возможности БСП (Библиотеки Стандартных Подсистем) и надежные архитектурные решения.

Суть проблемы: почему сообщения не видны?

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

Чтобы пользователь их увидел, клиентское приложение должно:

  1. Дождаться завершения задания (или периодически проверять его статус).
  2. Принудительно "забрать" накопленные сообщения из задания.
  3. Отобразить их в текущем контексте формы.

Способ 1. Стандартный механизм платформы (Ретрансляция)

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

Внутри фонового задания (на сервере) мы формируем сообщение:


// Код внутри фонового метода
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Расчет завершен успешно. Сумма: " + Сумма;
Сообщение.Сообщить();

На клиенте, после того как мы поняли, что задание выполнено, нам нужно получить эти сообщения. Основная ошибка — пытаться просто вывести полученные объекты. Часто требуется "пересоздать" сообщение или использовать общие модули, чтобы привязать его к текущей форме (установить правильный идентификатор назначения).

Пример кода на клиенте (или в процедуре оповещения):


&НаСервере
Функция ПолучитьИВывестиСообщенияФона(ИдентификаторЗадания, УИДФормы)
    
    Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
    
    // Получаем массив сообщений. Внимание: этот метод очищает буфер сообщений задания!
    МассивСообщений = Задание.ПолучитьСообщенияПользователю();
    
    Для Каждого СообщениеИзФона Из МассивСообщений Цикл
        // Создаем "прокси" сообщение, чтобы привязать его к текущей форме
        НовоеСообщение = Новый СообщениеПользователю;
        НовоеСообщение.Текст = СообщениеИзФона.Текст;
        
        // Важный момент: привязываем к текущей форме, чтобы сообщение не потерялось
        НовоеСообщение.ИдентификаторНазначения = УИДФормы; 
        
        // Если нужно привязать к полю
        НовоеСообщение.Поле = СообщениеИзФона.Поле;
        НовоеСообщение.КлючДанных = СообщениеИзФона.КлючДанных;
        
        НовоеСообщение.Сообщить();
    КонецЦикла;

КонецФункции

Также можно использовать стандартную процедуру из справочника методов БСП, если она доступна в вашей конфигурации:


// Вместо ручного создания объекта СообщениеПользователю
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(СообщениеИзФона.Текст);

Способ 2. Использование БСП (Длительные Операции)

Если вы работаете в типовой конфигурации (Бухгалтерия, УТ, ERP), лучше использовать механизмы БСП. Модуль ДлительныеОперации берет на себя значительную часть работы.

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


&НаСервереБезКонтекста
Функция ПолучитьСообщенияФоновогоЗадания(ФоновоеЗадание)
    Если ФоновоеЗадание <> Неопределено Тогда
        // Метод БСП, который корректно извлекает сообщения
        Возврат ДлительныеОперации.СообщенияПользователю(, ФоновоеЗадание);
    КонецЕсли;
КонецФункции

Важный нюанс: Метод получения сообщений "считывает" их с удалением. Если вы вызвали его один раз (например, для логирования), второй вызов вернет пустой массив. Это частая причина ошибок, когда программист видит, что сообщений "нет".

Способ 3. Передача через Временное Хранилище (Самый надежный)

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

Шаг 1. В фоновом задании:

Вместо (или вместе с) Сообщить() мы собираем данные в структуру или таблицу значений (например, если нужен индикатор прогресса в ячейке списка) и помещаем их во временное хранилище.


// Процедура фонового задания
Функция ВыполнитьРасчет(АдресВХ) Экспорт
    
    МассивСообщений = Новый Массив;
    
    // ... какой-то код ...
    Если Ошибка Тогда
        СтруктураСообщения = Новый Структура("Текст, Поле", "Ошибка расчета", "Объект.Сумма");
        МассивСообщений.Добавить(СтруктураСообщения);
    КонецЕсли;
    
    Результат = Новый Структура;
    Результат.Вставить("Данные", ПолученныеДанные);
    Результат.Вставить("МассивСообщений", МассивСообщений);
    
    // Помещаем результат по адресу, который передал клиент
    ПоместитьВоВременноеХранилище(Результат, АдресВХ);

КонецФункции

Шаг 2. На клиенте после завершения:

Когда задание завершилось, мы читаем данные из хранилища и сами решаем, как их показать.


&НаКлиенте
Процедура ПослеВыполненияЗадания(РезультатЗадания, ДополнительныеПараметры) Экспорт
    
    // Получаем структуру из адреса
    СтруктураРезультата = ПолучитьРезультатССервера(РезультатЗадания.АдресРезультата);
    
    // Обрабатываем наши сообщения
    Для Каждого ТекСообщ Из СтруктураРезультата.МассивСообщений Цикл
        
        // Используем универсальный метод БСП для вывода
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
            ТекСообщ.Текст, 
            , 
            ТекСообщ.Поле
        );
        
    КонецЦикла;
    
КонецПроцедуры

Почему сообщения могут не появляться? Основные ошибки

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

Выводы

Для гарантированной доставки сообщений пользователю из фонового задания рекомендуем использовать комбинацию подходов. Если сообщений немного и они информационные — используйте ретрансляцию через ПолучитьСообщенияПользователю() с обязательной привязкой к УИДу формы. Если же требуется сложная логика обработки ошибок или передача данных — используйте временное хранилище для возврата результата.

← На главную