Разработка и Конфигурация · 11 мин
Чем модальные окна отличаются от блокирующих окон в 1С
Разбираем отличие модальных окон от блокирующих в 1С: принципы работы, методы ОткрытьФормуМодально и блокирующие вызовы, риски, примеры кода и рекомендации по выбору.
В разработке на платформе 1С:Предприятие понятия «модальное окно» и «блокирующее окно» часто смешивают, хотя за ними стоят разные механизмы. Модальность — это поведение окна: оно перехватывает ввод и не даёт пользователю переключиться на другие окна приложения, пока не будет закрыто. Блокировка — это поведение кода: выполнение встроенного языка приостанавливается до тех пор, пока окно не вернёт результат. Окно может быть модальным и блокирующим одновременно, но эти свойства не обязаны совпадать.
Практическое значение различия выросло после перехода платформы на асинхронную модель работы. В режиме «Такси» и в веб-клиенте синхронные блокирующие вызовы либо запрещены настройкой конфигурации, либо приводят к нестабильному поведению. Разработчику важно понимать, какой механизм он использует, чтобы код работал одинаково в тонком, толстом и веб-клиенте.
Ниже разобраны оба подхода: как они устроены внутри платформы, чем отличаются на уровне кода, где каждый уместен и как безопасно перевести старые модальные вызовы на современную асинхронную схему.
Что такое модальное окно в 1С
Модальное окно — это форма или диалог, который открывается поверх остальных окон и захватывает фокус ввода. Пока пользователь не закроет такое окно, он не может кликнуть по родительской форме, переключиться на другой документ или продолжить ввод в основном окне. Классические примеры — вопрос «Сохранить изменения?», окно ввода пароля, предупреждение об ошибке проведения документа.
Модальность решает задачу гарантированного внимания пользователя. Если дальнейшая работа невозможна без ответа (например, документ нельзя провести без выбора склада), модальное окно заставляет пользователя принять решение здесь и сейчас. Это снижает риск потери данных и логических ошибок, вызванных параллельными действиями.
Обратная сторона — жёсткость. Частые модальные окна раздражают пользователей и замедляют работу, особенно в потоковых операциях вроде массового ввода накладных. Поэтому современные интерфейсные практики рекомендуют заменять второстепенные модальные диалоги на немодальные уведомления и сообщения в панели состояния.
Что такое блокирующее окно и блокирующий вызов
Блокирующий вызов — это метод встроенного языка, который приостанавливает выполнение кода до получения результата. Пока пользователь не ответит на вопрос или не закроет форму, следующая строка программы не выполнится. Примеры классических блокирующих методов: Вопрос(), Предупреждение(), ВвестиЗначение(), ОткрытьФормуМодально().
Блокировка удобна для линейной логики: код читается сверху вниз, и результат диалога сразу доступен в переменной. Именно поэтому старые конфигурации в обычном приложении построены на блокирующих вызовах — это было просто и предсказуемо.
Проблема в том, что блокирующий вызов останавливает весь клиентский поток. В веб-клиенте это технически невозможно без специальных механизмов браузера, а в тонком клиенте приводит к «замораживанию» интерфейса. Поэтому платформа ввела свойство конфигурации «Режим использования модальности», и в большинстве современных решений блокирующие вызовы запрещены.
Ключевые отличия: сравнение механизмов
Чтобы не путать понятия, полезно сопоставить их по основным признакам. Модальность описывает окно, блокировка — поведение кода; они пересекаются, но не тождественны.
| Критерий | Модальное окно | Блокирующий вызов |
|---|---|---|
| Что блокируется | Интерфейс (другие окна) | Выполнение кода |
| Где проявляется | На уровне формы и оконного менеджера | На уровне встроенного языка |
| Типичные методы | ОткрытьФорму с РежимОткрытияОкна.БлокироватьОкноВладельца | Вопрос(), Предупреждение(), ОткрытьФормуМодально() |
| Возврат результата | Через оповещение или закрытие формы | Непосредственно как значение функции |
| Поддержка в веб-клиенте | Да | Ограничена или запрещена |
| Рекомендуемость | Допустима точечно | Считается устаревшим подходом |
Из таблицы видно главное: форма может быть модальной по отношению к окну-владельцу, но открываться неблокирующим методом ОткрытьФорму() с передачей описания оповещения. Именно такая комбинация — модальный интерфейс плюс асинхронный код — является рекомендуемой в современных конфигурациях.
Как это выглядит в коде
Устаревший блокирующий вариант выглядит линейно. Результат вопроса возвращается напрямую, и обработка продолжается в той же процедуре:
Результат = Вопрос("Провести документ?", РежимДиалогаВопрос.ДаНет);
Если Результат = КодВозвратаДиалога.Да Тогда
ПровестиДокумент();
КонецЕсли;
Современный асинхронный вариант использует описание оповещения. Выполнение кода не останавливается: платформа показывает диалог, а когда пользователь отвечает, вызывается указанная процедура-обработчик:
Оповещение = Новый ОписаниеОповещения("ПослеОтветаНаВопрос", ЭтотОбъект);
ПоказатьВопрос(Оповещение, "Провести документ?", РежимДиалогаВопрос.ДаНет);
&НаКлиенте
Процедура ПослеОтветаНаВопрос(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
ПровестиДокумент();
КонецЕсли;
КонецПроцедуры
Аналогичная пара существует для форм: вместо ОткрытьФормуМодально() используется ОткрытьФорму() с параметром описания оповещения о закрытии и, при необходимости, режимом открытия окна «Блокировать окно владельца» или «Блокировать весь интерфейс». Так форма остаётся модальной визуально, но код не блокируется.
Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияФормы", ЭтотОбъект);
ОткрытьФорму("Документ.Реализация.Форма.ФормаПодбора", Параметры, ЭтотОбъект, , , , Оповещение, РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);Когда какой подход выбирать
Выбор зависит от режима конфигурации, клиента и сценария. Если конфигурация работает в режиме использования модальности «Не использовать», блокирующие вызовы недоступны в принципе — вопрос выбора снимается. Если режим разрешает модальность (типично для старых конфигураций на поддержке), блокирующие методы допустимы, но любая доработка — повод перевести код на асинхронную схему.
Модальное окно оправдано, когда без ответа пользователя продолжать работу нельзя: подтверждение удаления данных, ввод критичного параметра, выбор варианта при конфликте. Немодальные формы и оповещения лучше подходят для подбора товаров, информационных сообщений и параллельной работы с несколькими документами.
Как выбрать подход
Типичные ошибки и риски
Самая частая ошибка — смешивание старой и новой модели в одной цепочке вызовов. Например, разработчик заменяет Вопрос() на ПоказатьВопрос(), но оставляет продолжение логики в той же процедуре после вызова. Код после ПоказатьВопрос() выполняется немедленно, не дожидаясь ответа, и программа работает с неопределённым результатом.
Вторая типичная проблема — потеря контекста в обработчике оповещения. Процедура-обработчик вызывается позже, и локальные переменные исходной процедуры уже недоступны. Нужные данные следует передавать через дополнительные параметры описания оповещения или хранить в реквизитах формы.
Третья ошибка — чрезмерное использование режима «Блокировать весь интерфейс». Такое окно мешает работе даже с другими открытыми документами, а при ошибке в обработчике закрытия пользователь может оказаться в ситуации, когда приложение выглядит «зависшим». Блокируйте только то окно, которое действительно является владельцем диалога.
Как проверить и безопасно перевести код
Перевод конфигурации на асинхронную модель начинается с поиска блокирующих вызовов. В конфигураторе выполните глобальный поиск по методам Вопрос(, Предупреждение(, ВвестиЗначение(, ВвестиСтроку(, ОткрытьФормуМодально(, ВыбратьИзСписка(. Каждое вхождение — кандидат на замену парой «Показать… + описание оповещения».
Порядок безопасной замены: сначала выделите код, зависящий от ответа пользователя, в отдельную экспортную процедуру-обработчик. Затем замените блокирующий вызов на асинхронный, передав нужные данные через структуру дополнительных параметров. После этого протестируйте сценарий во всех клиентах, которые использует ваша организация.
- 1Найдите блокирующий метод глобальным поиском по конфигурации
- 2Вынесите логику, зависящую от результата, в отдельную экспортную процедуру
- 3Создайте описание оповещения с указанием этой процедуры
- 4Замените вызов на асинхронный аналог (ПоказатьВопрос, ОткрытьФорму и т.д.)
- 5Передайте нужные данные через дополнительные параметры оповещения
- 6Протестируйте сценарий в тонком и веб-клиенте
Обязательно проверьте результат не только в толстом клиенте, но и в веб-клиенте, если он используется: именно там асинхронная модель проявляет все ошибки переноса. Убедитесь, что после ответа пользователя выполняется только нужная ветка логики и форма не остаётся в заблокированном состоянии.
Как проверить результат
Продолжение выполняется только после ответа пользователя
Код после вызова срабатывает сразу, до ответа
Диалог открывается, результат обрабатывается корректно
Ошибка выполнения или молчаливое завершение сценария
Родительское окно снова доступно для ввода
Интерфейс остаётся заблокированным или «зависшим»
Часто задаваемые вопросы
Можно ли сделать окно модальным без блокировки кода?
Да. Откройте форму методом ОткрытьФорму с режимом открытия «Блокировать окно владельца» и передайте описание оповещения о закрытии. Пользователь не сможет переключиться на родительское окно, но выполнение кода продолжится асинхронно.
Почему Вопрос() выдаёт ошибку в моей конфигурации?
Скорее всего, в свойствах конфигурации установлен режим использования модальности «Не использовать». В этом режиме все блокирующие методы запрещены. Замените Вопрос() на ПоказатьВопрос() с описанием оповещения.
Чем ПоказатьВопрос отличается от Вопрос функционально?
Набор кнопок, таймаут и оформление у них одинаковые. Разница только в механизме: Вопрос останавливает код и возвращает результат напрямую, ПоказатьВопрос возвращает управление сразу, а результат приходит в процедуру-обработчик оповещения.
Как передать данные в обработчик оповещения?
Через третий параметр конструктора ОписаниеОповещения — «ДополнительныеПараметры». Обычно туда помещают структуру с нужными значениями, и она целиком приходит вторым аргументом в процедуру-обработчик.
Нужно ли переписывать всю старую конфигурацию сразу?
Нет. Если конфигурация работает в режиме, разрешающем модальность, и не планируется переход на веб-клиент, блокирующие вызовы продолжат функционировать. Разумная стратегия — переводить на асинхронную модель те участки, которые дорабатываются по другим причинам.
Что выбрать для подтверждения удаления данных?
Модальный диалог с асинхронным вызовом: ПоказатьВопрос с кнопками «Да/Нет» и обработчиком, выполняющим удаление только при положительном ответе. Это гарантирует внимание пользователя и совместимо с современными режимами работы платформы.
Что важно запомнить
Модальность блокирует интерфейс, блокирующий вызов — выполнение кода. Современный стандарт 1С: модальные окна при необходимости, но всегда асинхронные вызовы через описание оповещения. Перевод старого кода делайте постепенно с обязательным тестированием в веб-клиенте.