При разработке регламентных заданий в среде 1С:Предприятие 8.3 начинающие специалисты часто сталкиваются с проблемой: методы Сообщить() или СообщениеПользователю, прекрасно работающие в обычных формах или обработках, внутри регламентного задания не выводят никаких окон на экран пользователя. Разберем ситуацию: регламентное задание выполняется на сервере в отдельном, фоновом сеансе. У этого сеанса нет «лица» — графического интерфейса, поэтому все отправленные сообщения просто записываются в лог этого фонового сеанса и исчезают после его завершения. Наша задача — передать информацию из этого «невидимого» серверного процесса в активный сеанс конкретного пользователя.
Рассмотрим подробно несколько эффективных способов решения этой задачи, начиная от классических методов с использованием базы данных и заканчивая современными инструментами платформы.
Проанализируем классический подход, который работает в любой конфигурации, даже если в ней не используется БСП (Библиотека стандартных подсистем). Суть метода заключается в создании «почтового ящика» в базе данных, куда регламентное задание будет складывать сообщения, а клиентское приложение будет их забирать. Альтернативный вариант организации взаимодействия можно изучить на примере разработки фоновых заданий с отслеживанием результата без использования БСП.
Шаг 1. Создание регистра. Создадим непериодический регистр сведений, например, ОчередьУведомлений. В качестве измерений добавим Пользователь (тип СправочникСсылка.Пользователи), а в ресурсы — ТекстСообщения и ДатаСобытия.
Шаг 2. Запись из регламентного задания. В модуле, где выполняется серверный код задания, вместо прямого вывода сообщения напишем код записи в регистр:
Процедура ВыборкаДокументовБезРегистрации() Экспорт
// ... логика поиска документов ...
Если НайденыОшибки Тогда
НоваяЗапись = РегистрыСведений.ОчередьУведомлений.СоздатьМенеджерЗаписи();
НоваяЗапись.Пользователь = ОтветственныйМенеджер;
НоваяЗапись.ТекстСообщения = "Обнаружены незарегистрированные документы!";
НоваяЗапись.ДатаСобытия = ТекущаяДата();
НоваяЗапись.Записать();
КонецЕсли;
КонецПроцедуры
Шаг 3. Получение на клиенте. В модуле управляемого приложения (или в основной форме) настроим периодическую проверку этого регистра с помощью метода ПодключитьОбработчикОжидания.
// В модуле управляемого приложения
Процедура ПриНачалеРаботыСистемы()
ПодключитьОбработчикОжидания("ПроверитьНовыеУведомления", 60); // Проверка раз в минуту
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьНовыеУведомления()
Текст = ПолучитьСообщениеИзРегистраСервер();
Если ЗначениеЗаполнено(Текст) Тогда
ПоказатьОповещениеПользователя("Внимание!", , Текст);
КонецЕсли;
КонецПроцедуры
Если ваша конфигурация построена на базе БСП, разберем более профессиональный подход. Как правильно замечено в обсуждении, БСП предоставляет механизмы для мониторинга фоновых заданий. Однако важно различать: регламентное задание (запускается сервером по расписанию) и фоновое задание (запускается пользователем интерактивно).
Для интерактивных задач (например, тяжелый отчет) мы используем ДлительныеОперации.ЗапуститьВыполнениеВФоне. В этом случае мы можем считывать сообщения, используя метод СообщенияПользователю() из модуля ДлительныеОперации. Но для именно регламентных заданий, работающих автономно, лучше подходит механизм «Напоминания пользователя». Разобраться в тонкостях реализации таких фоновых процессов поможет руководство по использованию длительных операций в актуальных версиях БСП.
Рассмотрим, как программно создать напоминание в БСП:
// Пример создания напоминания через программный интерфейс БСП
ПараметрыНапоминания = Новый Структура;
ПараметрыНапоминания.Вставить("Пользователь", ПользовательСсылка);
ПараметрыНапоминания.Вставить("ВремяНапоминания", ТекущаяДата());
ПараметрыНапоминания.Вставить("Описание", "Проверьте входящие документы!");
ПараметрыНапоминания.Вставить("Источник", ДокументСсылка); // Ссылка на объект
НапоминанияПользователя.СоздатьНапоминание(ПараметрыНапоминания);
Преимущество этого метода в том, что система сама покажет стандартное окно напоминания пользователю, когда он будет в программе, без необходимости писать свои обработчики ожидания.
Выясним, какой способ является самым современным. Система взаимодействия позволяет серверу напрямую «толкнуть» сообщение клиенту. Это работает мгновенно и не нагружает базу данных постоянными опросами регистров.
Разберем пример кода для отправки сообщения конкретному пользователю:
// Код выполняется в регламентном задании на сервере
ПользовательОбъект = Пользователи.ИнформационнаяБазаПользователь(НужныйПользователь);
ИдентификаторПользователя = СистемаВзаимодействия.ИдентификаторПользователя(ПользовательОбъект.УникальныйИдентификатор);
// Ищем или создаем обсуждение между сервером (системой) и пользователем
Отбор = Новый Структура;
МассивУчастников = Новый Массив;
МассивУчастников.Добавить(ИдентификаторПользователя);
Отбор.Вставить("Участники", МассивУчастников);
Обсуждения = СистемаВзаимодействия.ПолучитьОбсуждения(Отбор);
Если Обсуждения.Количество() > 0 Тогда
Обсуждение = Обсуждения[0];
Иначе
Обсуждение = СистемаВзаимодействия.СоздатьОбсуждение();
Обсуждение.Участники.Добавить(ИдентификаторПользователя);
Обсуждение.Записать();
КонецЕсли;
НовоеСообщение = СистемаВзаимодействия.СоздатьСообщение(Обсуждение.Идентификатор);
НовоеСообщение.Текст = "Регламентное задание: обнаружены ошибки в данных!";
НовоеСообщение.Записать();
В этом случае у пользователя в правом нижнем углу или в панели обсуждений сразу появится уведомление, даже если он просто открыл программу и ничего не нажимает.
ПолучитьСообщенияПользователю не помогает автору вопроса?Проанализируем ошибку в первом сообщении темы. Автор пытается вызвать РЗ.ПолучитьСообщенияПользователю() внутри самого регламентного задания. Это логическая ошибка по двум причинам:
ПолучитьСообщенияПользователю предназначен для того, чтобы внешний сеанс (клиентский) мог прочитать сообщения, которые накопились внутри фонового сеанса. Вызывать его внутри самого себя бессмысленно — он вернет те сообщения, которые вы только что создали через Сообщить(), но они всё равно останутся внутри этого фонового сеанса.Подведем итог и выберем оптимальный путь для вашей ситуации:
ЗаписьЖурналаРегистрации. Это стандарт де-факто для системных логов.Использование любого из этих методов позволит вам сделать работу фоновых процессов прозрачной и информативной для конечных пользователей, избегая ситуации «молчаливого» выполнения важных бизнес-задач.