Почему не закрывается форма внешней обработки в 1С 8.3 и как это исправить?

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

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

Анализ структуры кода и последовательности вызовов

Проанализируем типичный сценарий: у нас есть команда формы, которая должна выполнить обработку данных на сервере и затем закрыть окно. Стандартная реализация выглядит следующим образом:


&НаКлиенте
Процедура ВыполнитьДействие(Команда)
    
    // Вызов серверной процедуры для обработки данных
    ВыполнитьДействиеНаСервере();
    
    // Попытка закрыть форму после завершения работы на сервере
    ЭтаФорма.Закрыть();
    
КонецПроцедуры

&НаСервере
Процедура ВыполнитьДействиеНаСервере()
    
    // Пример логики: изменение реквизитов объектов
    Для каждого Ссылка Из Объект.СписокОбъектов Цикл
        ОбъектСправ = Ссылка.ПолучитьОбъект();
        ОбъектСправ.СтавкаНДС = Объект.НоваяСтавкаНДС;
        ОбъектСправ.Записать();
    КонецЦикла;
    
КонецПроцедуры

На первый взгляд, код абсолютно корректен. Однако, если после вызова ВыполнитьДействиеНаСервере() управление не возвращается в клиентский поток должным образом или происходит "тихое" прерывание, команда Закрыть() не будет выполнена. Выясним основные причины, почему это происходит.

Причина 1: Кэширование внешних обработок

Когда мы используем внешнюю обработку через справочник "Дополнительные отчеты и обработки", платформа копирует файл обработки во временный каталог пользователя. Если вы внесли изменения в код (например, добавили команду Закрыть()), но не обновили файл в справочнике или платформа продолжает открывать старую версию из локального кэша, изменения не вступят в силу.

Рассмотрим алгоритм действий для исключения влияния кэша:

  1. Удалите обработку из списка дополнительных отчетов и обработок.
  2. Очистите временные файлы пользователя (папка %TEMP%) и кэш конфигурации 1С.
  3. Измените Имя и Синоним обработки в конфигураторе (например, добавьте текущую дату в конец имени). Это заставит платформу воспринять объект как новый.
  4. Заново зарегистрируйте обработку в информационной базе.

Причина 2: Необработанные исключения на сервере

Если внутри серверного цикла происходит ошибка (например, объект заблокирован другим пользователем или не заполнен обязательный реквизит), и эта ошибка не обернута в блок Попытка...Исключение, выполнение кода прерывается. В некоторых контекстах (особенно в дополнительных обработках) это приводит к тому, что клиентский код, следующий за серверным вызовом, просто не запускается.

Проанализируем ситуацию и добавим безопасную обработку ошибок:


&НаКлиенте
Процедура УстановитьНДС(Команда)
    
    Попытка
        УстановитьНДСНаСервере();
        // Если сервер отработал успешно, закрываем форму
        Закрыть();
    Исключение
        // Сообщаем пользователю о проблеме, форма остается открытой для анализа
        ТекстОшибки = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Ошибка при выполнении: " + ТекстОшибки);
    КонецПопытки;
    
КонецПроцедуры

Использование метода ОбщегоНазначенияКлиентСервер.СообщитьПользователю (из состава БСП) позволяет гарантированно вывести текст ошибки, даже если стандартное системное окно сообщения блокируется контекстом выполнения.

Причина 3: Особенности платформы 8.3.27 и ошибки релизов

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

Посмотрим на способы обхода этой проблемы:

Пример использования отложенного закрытия:


&НаКлиенте
Процедура ЗавершитьРаботуАсинхронно()
    Закрыть();
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьИЗакрыть(Команда)
    ВыполнитьНаСервере();
    // Подключаем однократный обработчик ожидания на 0.1 секунды
    ПодключитьОбработчикОжидания("ЗавершитьРаботуАсинхронно", 0.1, Истина);
КонецПроцедуры

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

Методы диагностики: как понять, где "зависает" код

Если отладка внешней обработки затруднена (например, она запущена в составе БСП), воспользуемся методом Сообщить(). Важно расставить контрольные точки до и после серверного вызова:


&НаКлиенте
Процедура ТестЗакрытия(Команда)
    Сообщить("Начало выполнения...");
    УстановитьНДСНаСервере();
    Сообщить("Вернулись с сервера!");
    Закрыть();
    Сообщить("Команда Закрыть отправлена");
КонецПроцедуры

Если в окне сообщений вы видите "Начало выполнения...", но не видите "Вернулись с сервера!", значит, проблема локализована внутри серверной процедуры (происходит зависание или критическая ошибка). Если же вы видите все сообщения, но форма висит — это прямое указание на баг платформы или блокировку интерфейса модальным окном/владельцем формы.

Важный момент для Розницы 2.3 и других конфигураций на БСП: При программном изменении объектов на сервере рекомендуется использовать метод Оповестить("Записан_Объект", Параметры, ЭтаФорма). Это позволит другим открытым формам (например, списку номенклатуры) узнать об изменениях и обновить данные после того, как ваша обработка закроется.

Резюме

Для решения проблемы с закрытием формы выполните следующие действия в указанном порядке:

  1. Проверьте, не происходит ли ошибка в цикле на сервере, обернув код в Попытка...Исключение.
  2. Убедитесь, что вы работаете с актуальной версией обработки (измените имя/синоним и перезалейте в базу).
  3. Если используете версию 8.3.27.1719, попробуйте протестировать работу на другом релизе платформы.
  4. В крайнем случае используйте ПодключитьОбработчикОжидания для разнесения серверного вызова и закрытия формы во времени.
← На главную