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