Разработчики на платформе 1С:Предприятие 8.3 часто сталкиваются с ситуацией, когда стандартный метод ОчиститьСообщения(), вызванный на клиенте, кажется абсолютно бесполезным. Сообщения, которые должны были исчезнуть, продолжают висеть в окне сообщений или «прилипают» к полям формы. В этой статье мы подробно разберем, почему так происходит, изучим внутренние механизмы работы платформы и найдем эффективные способы решения этой задачи.
Для начала проанализируем ситуацию, в которой оказался автор темы. Он пытается вызвать ОчиститьСообщения() в той же процедуре, где ранее (или параллельно) генерируются сообщения. Проблема здесь кроется не в программной ошибке, а в архитектуре управляемого приложения.
В управляемых формах вывод сообщений через объект СообщениеПользователю или метод Сообщить() работает по принципу буферизации. Когда выполняется код на встроенном языке, сообщения не выводятся на экран мгновенно. Вместо этого они накапливаются в специальном буфере клиентской части платформы. Реальная визуализация (отрисовка окна сообщений) происходит только в тот момент, когда управление возвращается системе, то есть по завершении работы всей цепочки процедур на стороне клиента.
Рассмотрим последовательность действий, которую видит платформа:
&AtClient.ОчиститьСообщения(), который очищает этот самый буфер.Однако, если сообщения были инициированы серверным вызовом и уже отображены в интерфейсе, попытка их очистить в следующей клиентской процедуре также может провалиться. Это происходит из-за того, что платформа может считать сообщения «актуальными» до тех пор, пока пользователь не произведет какое-либо действие с формой или пока не сработает валидация данных.
Как выяснили участники обсуждения, одним из способов заставить систему очистить сообщения является использование метода ПодключитьОбработчикОжидания(). Смысл этого подхода в том, чтобы разорвать стек выполнения и дождаться момента, когда система закончит отрисовку интерфейса.
Рассмотрим, как реализовать этот механизм по шагам. Сначала создадим вспомогательную процедуру для очистки:
&AtClient
Процедура ВыполнитьОчисткуСообщений()
ОчиститьСообщения();
КонецПроцедуры
Затем в основном коде, где нам необходимо выполнить очистку, мы не вызываем метод напрямую, а подключаем обработчик с минимальным интервалом (например, 0.1 секунды):
&AtClient
Процедура ОчиститьМастерПриНажатии(Команда)
// Основная логика процедуры
ЛичныеДанные = Истина;
СтрокиТаблицы.Очистить();
// Вместо прямой очистки подключаем обработчик
ПодключитьОбработчикОжидания("ВыполнитьОчисткуСообщений", 0.1, Истина);
КонецПроцедуры
Важно понимать: этот метод имеет визуальный недостаток. Пользователь может заметить «эффект вспышки» — когда окно сообщений на долю секунды появляется и тут же исчезает. Это происходит потому, что в первом цикле событий система отрисовывает сообщения, а во втором (через 0.1 сек) — исполняет команду очистки.
Наиболее «чистым» и профессиональным решением считается не борьба с уже выведенными сообщениями, а предотвращение их появления. Если в определенном контексте (например, при работе «Мастера настройки») нам не нужно показывать стандартные сообщения об ошибках или уведомления, мы можем управлять этим через переменные формы.
Проанализируем пример реализации такого подхода. Введем на форме реквизит (или переменную) НеВыводитьСообщения типа Булево.
&AtClient
Процедура ВывестиИнформацию(ТекстСообщения)
// Проверяем флаг перед выводом
Если Не НеВыводитьСообщения Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = ТекстСообщения;
Сообщение.Сообщить();
КонецЕсли;
КонецПроцедуры
В этом случае при выполнении специфических действий мы просто устанавливаем НеВыводитьСообщения = Истина, и метод ОчиститьСообщения() нам вообще не потребуется. Это исключает лишнее мерцание интерфейса и делает работу программы более предсказуемой.
Нужно учитывать, что метод ОчиститьСообщения() гарантированно работает только с общим окном сообщений. Если вы используете СообщениеПользователю с установленными свойствами Поле или ПутьКДанным, такие сообщения ведут себя иначе.
Выясним причину: такие уведомления «привязываются» к конкретным элементам управления (например, подчеркивают поле ввода красным пунктиром). Чтобы убрать такие сообщения, платформа должна выполнить повторную проверку данных формы. В некоторых случаях помогает принудительный вызов метода ОбновитьОтображениеДанных() после очистки, но это не всегда дает 100% результат для связанных сообщений.
&AtClient
Процедура ОчиститьВсеДанные()
ОчиститьСообщения();
ЭтаФорма.ОбновитьОтображениеДанных();
КонецПроцедуры
Если ваша цель — информировать пользователя о ходе процесса без замусоривания окна сообщений (которое потом придется мучительно очищать), проанализируем альтернативы:
Состояние(): Выводит текст в небольшое всплывающее окно в углу экрана, которое исчезает само через некоторое время.СтатусТекста: Позволяет выводить информацию в строку состояния (нижняя панель). Она не требует принудительной очистки, так как новое сообщение просто заменяет старое.Декорация - Надпись, текст которой меняется программно. Это самый надежный способ управления вниманием пользователя в рамках конкретного бизнес-процесса.Стоит отметить, что в современных версиях платформы (как упоминалось в сообщении №12, версия 8.3.21.1674), сообщения могут кэшироваться в истории уведомлений (значок «колокольчик»). Метод ОчиститьСообщения() влияет только на текущее активное окно и визуальные индикаторы у полей, но он не удаляет записи из истории уведомлений. Это поведение является штатным для интерфейса «Такси».
Подведем итог: если ОчиститьСообщения() не срабатывает, проверьте, не вызываете ли вы его в той же процедуре, где происходит генерация текста. Попробуйте разнести эти действия во времени с помощью ПодключитьОбработчикОжидания() или, что более правильно, пересмотрите логику вывода сообщений, внедрив условия (флаги), при которых вызов Сообщить() просто не будет производиться.