Начиная с версии платформы 8.3.8 (при отключении режима совместимости или установке совместимости с версиями 8.3.8, 8.3.10 и выше), разработчики сталкиваются с критическим изменением: блокировкой синхронных серверных вызовов и интерактивных окон при завершении работы программы. Разберем причины этого нововведения платформы, рассмотрим примеры обхода и выделим рекомендованные архитектурные решения.
Выясним причину, почему разработчики платформы пошли на такие ограничения. Главным фактором стала унификация работы тонкого клиента и веб-клиента. В веб-браузерах при закрытии вкладки или окна невозможно гарантировать выполнение синхронных сетевых запросов к серверу или отображение модальных диалогов.
В связи с этим платформа 1С блокирует любые серверные вызовы и модальные взаимодействия в следующих событиях:
ПередЗавершениемРаботыСистемы(Отказ, ТекстПредупреждения).ПриЗавершенииРаботыСистемы().ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка) при значении ЗавершениеРаботы = Истина.ПриЗакрытии(ЗавершениеРаботы) при значении ЗавершениеРаботы = Истина.Кроме того, изменилось поведение параметра Отказ = Истина: платформа больше не отменяет завершение работы немедленно и программно. Вместо этого пользователю показывается стандартный системный диалог с возможностью завершить работу или остаться в программе. Если пользователь подтверждает закрытие, сеанс завершается принудительно без шанса выполнить серверный код.
Посмотрим на практический пример, предложенный разработчиками для ситуаций, когда при выходе необходимо выполнить служебные действия с открытыми формами или передать данные на сервер. Идея заключается в установке отказа от закрытия и немедленном подключении однократного обработчика ожидания.
Разберем по шагам реализацию в клиентском модуле:
Процедура ПередЗавершениемРаботыСистемы(Отказ, ТекстПредупреждения) Экспорт
Если АСФСерверныеВызовыЗапрещены = Истина Тогда
Возврат;
КонецЕсли;
// Блокируем текущую попытку завершения
Отказ = Истина;
// Подключаем однократный обработчик ожидания для выполнения действий вне контекста закрытия
ПодключитьОбработчикОжидания("АСФПодключаемый_ПередЗавершениемРаботыСистемы", 0.1, Истина);
КонецПроцедуры
Теперь рассмотрим саму процедуру, вызываемую обработчиком ожидания. В ней система находится уже в обычном клиентском контексте, где разрешены серверные вызовы и манипуляции с интерфейсом:
Процедура АСФПодключаемый_ПередЗавершениемРаботыСистемы() Экспорт
Отказ = Ложь;
// Вызов стандартных механизмов БСП и оборудования
СтандартныеПодсистемыКлиент.ПередЗавершениемРаботыСистемы(Отказ);
МенеджерОборудованияКлиент.ПередЗавершениемРаботыСистемы();
// Обход всех открытых окон и закрытие/обработка особых форм
Окна = ПолучитьОкна();
МассивОсобыхФорм = Новый Массив;
МассивОсобыхФорм.Добавить("Обработка.ТекущиеДела.Форма.Форма");
Для Каждого ТекущееОкно Из Окна Цикл
Для Каждого ТекущаяФорма Из ТекущееОкно.Содержимое Цикл
Если МассивОсобыхФорм.Найти(ТекущаяФорма.ИмяФормы) <> Неопределено Тогда
Попытка
ТекущаяФорма.АСФВыполнитьПередЗакрытием();
Исключение
// Обработка исключений при вызове методов формы
КонецПопытки;
Иначе
ТекущаяФорма.Закрыть();
КонецЕсли;
КонецЦикла;
КонецЦикла;
// Взводим флаг для предотвращения повторной блокировки
АСФСерверныеВызовыЗапрещены = Истина;
// Повторно инициируем корректное завершение работы
ЗавершитьРаботуСистемы(Ложь);
КонецПроцедуры
Важное замечание: данный подход позволяет обойти ограничение в тонком клиенте, однако в веб-клиенте при прямом закрытии вкладки браузера этот механизм работать не будет, так как браузер просто уничтожает поток JavaScript.
Проанализируем правильные с точки зрения архитектуры 1С способы работы с данными при завершении сеанса:
Для предотвращения падений системы рекомендуется включить встроенный контроль конфигуратора. Для этого перейдите в меню: Сервис → Параметры → Запуск 1С:Предприятия и установите флаг проверки серверных вызовов в обработчиках событий.
Также обратите внимание на сопутствующие изменения платформы при переходе на режим совместимости 8.3.10. В запросах ужесточился контроль типов: запрещено объединять через ОБЪЕДИНИТЬ ВСЕ поля разных типов, если одно из них является строкой неограниченной длины. В отчетах на СКД при передаче строковых констант в параметры необходимо явно указывать ограничение длины строки (например, Строка(50)), иначе запросы будут завершаться с ошибкой.