При разработке дополнительных обработок в конфигурациях на базе 1С:Библиотека стандартных подсистем (БСП) программисты часто сталкиваются с проблемой: команда с типом «Вызов серверного метода» выполняется в фоновом задании. Это означает, что привычный метод Сообщить(), вызванный в коде серверного модуля обработки, не выведет текст в окно сообщений пользователя, так как фоновое задание работает в отдельном сеансе на сервере. Рассмотрим подробно, как решить эту задачу и обеспечить качественную обратную связь для пользователя.
Разберем ситуацию: вы создаете дополнительную обработку, которая должна обмениваться данными с внешними базами через OData. Чтобы интерфейс пользователя не «зависал» на время обмена, БСП запускает ваш серверный метод как фоновое задание. Все сообщения, генерируемые внутри этого задания, накапливаются в специальном массиве на сервере, но не передаются автоматически в клиентское приложение, если это не настроено явно. Проанализируем основные способы «доставки» этих сообщений до экрана пользователя.
В современных версиях БСП запуск серверных методов обработок осуществляется через общую форму ДополнительныеОтчетыИОбработки. Чтобы сообщения из фонового задания начали отображаться, необходимо убедиться, что в параметрах ожидания установлен соответствующий флаг. Выясним, как это реализовать через расширение формы.
Рассмотрим пример перехвата процедуры запуска команды в расширении формы:
&Вместо("ВыполнитьСерверныйМетодОбработки")
&НаКлиенте
Процедура ИмяРасширения_ВыполнитьСерверныйМетодОбработки()
// Запускаем стандартный механизм формирования фонового задания
Задание = ЗапуститьФоновоеЗадание(ВыполняемаяКоманда, УникальныйИдентификатор);
// Настраиваем параметры ожидания завершения
НастройкиОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
// Указываем системе, что нужно выводить окно ожидания (прогресс-бар)
НастройкиОжидания.ВыводитьОкноОжидания = Истина;
// КРИТИЧЕСКИ ВАЖНО: устанавливаем флаг вывода сообщений
НастройкиОжидания.ВыводитьСообщения = Истина;
// Устанавливаем обработчик завершения
Обработчик = Новый ОписаниеОповещения("ВыполнитьСерверныйМетодОбработкиЗавершение", ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(Задание, Обработчик, НастройкиОжидания);
КонецПроцедуры
Иногда даже при включенном флаге ВыводитьСообщения уведомления не появляются на экране, если форма, инициировавшая вызов, закрывается слишком быстро или если контекст вывода теряется. В этом случае проанализируем механизм ручного получения сообщений из объекта фонового задания в процедуре завершения.
Посмотрим на пример кода, который позволяет программно «привязать» сообщения к форме владельца (например, к списку документов, из которого была нажата кнопка):
&Вместо("ВыполнитьСерверныйМетодОбработкиЗавершение")
&НаКлиенте
Процедура ИмяРасширения_ВыполнитьСерверныйМетодОбработкиЗавершение(Задание, ДополнительныеПараметры) Экспорт
Если Задание = Неопределено Тогда
Возврат;
КонецЕсли;
// Проверяем статус выполнения
Если Задание.Статус = "Выполнено" Тогда
// Если в задании накопились сообщения, выведем их
Если Задание.Сообщения.Количество() > 0 Тогда
Для Каждого Сообщ Из Задание.Сообщения Цикл
// Привязываем сообщение к идентификатору формы-владельца
// Это заставит систему показать сообщение в текущем интерфейсе
Сообщ.ИдентификаторНазначения = ВладелецФормы.УникальныйИдентификатор;
Сообщ.Сообщить();
КонецЦикла;
КонецЕсли;
// Показываем стандартное оповещение
Если ВыполняемаяКоманда.ПоказыватьОповещение Тогда
ПоказатьОповещениеПользователя(НСтр("ru = 'Команда выполнена'"),, ВыполняемаяКоманда.Представление);
КонецЕсли;
ИначеЕсли Задание.Статус = "Ошибка" Тогда
// Обработка критических ошибок фонового задания
ВызватьИсключение Задание.КраткоеПредставлениеОшибки;
КонецЕсли;
// Закрываем форму обработки, если она открыта
Если Открыта() Тогда
Закрыть();
КонецЕсли;
КонецПроцедуры
Для сложных обменов данными (как в случае с OData) простого текстового сообщения часто недостаточно. Рассмотрим более продвинутый подход: передачу структуры данных из фонового задания.
Сообщить() формируйте структуру или таблицу с результатами. Поместите её во временное хранилище, адрес которого передается в ДлительныеОперации.ЗаписатьРезультат.ПолучитьИзВременногоХранилища(Задание.АдресРезультата).Разберем, почему это удобно: вы можете передать массив структур, содержащий GUID созданных объектов, тексты конкретных ошибок OData-запросов и статистику. На клиенте эти данные можно вывести не просто в окно сообщений, а открыть специальную форму протокола обмена.
Важно помнить, что если в вашем серверном методе произойдет необработанное исключение (ВызватьИсключение), фоновое задание прервется со статусом «Ошибка». Текст этой ошибки будет доступен в свойстве Задание.ПодробноеПредставлениеОшибки.
Если же вы используете конструкцию Попытка...Исключение внутри обмена OData, чтобы продолжить обработку других баз, задание сохранит статус «Выполнено». В этом случае вы обязаны либо использовать СообщениеПользователю, либо записывать ошибки в структуру результата, иначе пользователь никогда не узнает о возникших проблемах в середине процесса.
Совет: Если сообщений много, рекомендуется собрать их в одну строку через Символы.ПС перед выводом, чтобы не перегружать интерфейс десятками всплывающих окон, которые могут перекрывать друг друга.
Для очень длительных процессов (десятки минут или часы) рассмотренные методы могут быть неудобны, так как пользователь может закрыть сеанс или переключиться на другую задачу. В таких сценариях эффективнее использовать:
Выясним итог: для быстрых команд «Вызова серверного метода» оптимальным является сочетание настройки НастройкиОжидания.ВыводитьСообщения = Истина и программного контроля Сообщ.ИдентификаторНазначения в процедуре обратного вызова.