Как определить завершение работы системы в событии ПередЗакрытием формы справочника

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

В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью выполнить определенные действия при закрытии формы. Однако возникает специфическая задача: как понять, закрывает ли пользователь конкретное окно справочника или же происходит полное завершение работы приложения? Это критически важно для оптимизации производительности, так как при выходе из системы крайне нежелательно выполнять тяжелые серверные вызовы, которые могут привести к ошибкам или зависанию сеанса. Рассмотрим подробно, как решить эту задачу.

Анализируем состав параметров события ПередЗакрытием

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

Проанализируем стандартную подпись процедуры:


&НаКлиенте
Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)
    // Код обработчика
КонецПроцедуры

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

  1. Отказ (Булево) — позволяет прервать закрытие формы, если установить значение Истина.
  2. ЗавершениеРаботы (Булево) — ключевой параметр. Если он равен Истина, значит, форма закрывается потому, что пользователь выходит из 1С или завершается сеанс.
  3. ТекстПредупреждения (Строка) — если заполнить этот параметр, система покажет стандартный вопрос пользователю при закрытии.
  4. СтандартнаяОбработка (Булево) — определяет, нужно ли выполнять системные действия после завершения кода процедуры.

Если в вашем справочнике при создании обработчика через конфигуратор автоматически создается только два параметра (Отказ и СтандартнаяОбработка), это может свидетельствовать о том, что конфигурация работает в режиме совместимости с очень старыми версиями платформы или вы используете "Обычные формы". В современном управляемом приложении всегда доступны все четыре параметра.

Почему важно проверять флаг ЗавершениеРаботы?

Выясним причину, по которой стоит избегать серверных вызовов при выходе из программы. Когда ЗавершениеРаботы имеет значение Истина, сеанс пользователя находится в стадии терминации. Попытка вызвать процедуру &НаСервере в этот момент может привести к следующим проблемам:

Посмотрим на пример правильной логики в форме справочника:


&НаКлиенте
Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)
    
    Если ЗавершениеРаботы Тогда
        // Если система закрывается, просто выходим из процедуры, 
        // не выполняя лишних действий и серверных вызовов.
        Возврат;
    КонецЕсли;

    // Здесь располагается логика, которая должна выполняться 
    // ТОЛЬКО при обычном закрытии формы пользователем
    ПроверитьЗаполненностьДанныхНаСервере();
    
КонецПроцедуры

Использование глобального обработчика в Модуле управляемого приложения

Если по каким-то причинам вы работаете в условиях, где параметр ЗавершениеРаботы недоступен напрямую в форме, или вам нужно централизованно управлять состоянием закрытия, рассмотрим вариант с использованием Модуля управляемого приложения. Мы можем перехватить событие закрытия всей системы и оповестить об этом все открытые формы.

Разберем по шагам реализацию этого механизма:

1. В Модуле управляемого приложения создадим обработчик события ПередЗавершениемРаботыСистемы:


&НаКлиенте
Процедура ПередЗавершениемРаботыСистемы(Отказ, ТекстПредупреждения)
    // Устанавливаем глобальный флаг, который будет доступен на клиенте
    ПараметрыКлиента.Вставить("ПриложениеЗакрывается", Истина);
КонецПроцедуры

2. В форме справочника проверяем этот флаг. Для этого можно использовать экспортную переменную глобального модуля или параметры клиента:


&НаКлиенте
Процедура ПередЗакрытием(Отказ, СтандартнаяОбработка)
    
    // Пытаемся получить наш флаг из параметров клиента
    ЗакрытиеСистемы = Ложь;
    ПараметрыКлиента.Свойство("ПриложениеЗакрывается", ЗакрытиеСистемы);
    
    Если ЗакрытиеСистемы Тогда
        Возврат; // Никаких серверных вызовов
    КонецЕсли;
    
    // Логика обычного закрытия
    ОповеститьОЗакрытииФормы();
    
КонецПроцедуры

Особенности программного закрытия всех форм

Проанализируем ситуацию, когда закрытие инициируется программно. Если вы используете метод ЗавершитьРаботуСистемы(Ложь), платформа автоматически разошлет во все открытые формы событие ПередЗакрытием с установленным параметром ЗавершениеРаботы = Истина.

Однако, если вы используете метод ЗакрытьВсеФормы(), это имитирует последовательное закрытие окон пользователем. В этом случае параметр ЗавершениеРаботы будет равен Ложь. Это важное различие, которое необходимо учитывать при проектировании логики выхода из специализированных интерфейсов (например, рабочих мест кассира или менеджера).

Рекомендации по оптимизации процесса закрытия

Для создания качественного программного продукта придерживайтесь следующих правил:

  1. Всегда проверяйте ЗавершениеРаботы перед вызовом процедур &НаСервере в формах.
  2. Если вам нужно сохранить состояние формы (например, положение окна или настройки фильтров), делайте это в событии ПриЗакрытии, но помните, что там параметр ЗавершениеРаботы отсутствует. Поэтому значение этого флага нужно сохранять в переменную формы в обработчике ПередЗакрытием.
  3. Используйте параметр ТекстПредупреждения вместо модальных окон Вопрос(). При завершении работы системы модальные окна могут блокировать процесс или игнорироваться системой, тогда как заполненный ТекстПредупреждения корректно обрабатывается платформой.

Таким образом, мы выяснили, что наиболее надежным и современным способом определения закрытия приложения в форме справочника является использование штатного параметра ЗавершениеРаботы. Если же ваша версия платформы специфична, использование глобальных флагов в модуле управляемого приложения станет отличной альтернативой, гарантирующей стабильность работы вашей конфигурации.

← На главную