В процессе разработки на платформе 1С:Предприятие 8.3 начинающие специалисты часто сталкиваются с ситуацией, когда стандартный метод Вопрос() ведет себя непредсказуемо: форма «замирает», интерфейс перестает откликаться на действия пользователя в течение минуты, а программное обновление данных в табличной части не происходит. Особенно остро эта проблема проявляется при работе через удаленный рабочий стол (RDP) или в режиме RemoteApp. Разберем детально причины этих явлений и выясним, как правильно организовать диалог с пользователем в современных управляемых формах.
Проанализируем поведение метода Вопрос(). Этот метод является модальным. Это означает, что в момент его вызова выполнение программного кода полностью останавливается, и система ожидает ответа пользователя. В управляемом приложении, особенно в тонком клиенте, такое поведение считается устаревшим и нежелательным. Рассмотрим, почему это происходит:
РежимИспользованияМодальности = НеИспользовать, метод Вопрос() попросту вызовет исключение. Однако даже если модальность включена, современные браузеры и средства публикации могут блокировать такие окна.Для решения этой задачи в управляемых формах необходимо использовать асинхронный подход. Вместо блокирующего вызова мы должны использовать метод ПоказатьВопрос().
Рассмотрим по шагам, как переписать обработчик события ПриИзменении, чтобы избежать зависаний. Основная идея заключается в том, что мы не «ждем» ответа в текущей процедуре, а передаем управление специальной процедуре-оповещению.
Разберем пример правильной реализации:
&НаКлиенте
Процедура ЗаявкиНаТранспортСтатусПриИзменении(Элемент)
ТекущиеДанные = Элементы.ЗаявкиНаТранспорт.ТекущиеДанные;
// Если статус снят, дополнительные вопросы не задаем
Если Не ТекущиеДанные.Статус Тогда
Возврат;
КонецЕсли;
// Подготавливаем описание оповещения (куда вернуться после ответа пользователя)
Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияВопросаЗаявки", ЭтотОбъект);
// Вызываем неблокирующее окно
ТекстВопроса = "Выполнить обработку заявки?";
ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
// ВАЖНО: Весь код, который должен выполниться ПОСЛЕ ответа,
// НЕЛЬЗЯ писать ниже этой строки. Процедура завершится сразу.
КонецПроцедуры
&НаКлиенте
Процедура ПослеЗакрытияВопросаЗаявки(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
// Здесь выполняем основную логику
ОбработатьСтатусНаСервере();
// Обновляем визуальное отображение
ЭтаФорма.ОбновитьОтображениеДанных();
Иначе
// Если пользователь отказался, можно вернуть флажок в исходное состояние
// (потребуется хранить предыдущее значение)
КонецЕсли;
КонецПроцедуры
Выясним причину странного поведения, когда форма «отлипает» только после сворачивания-разворачивания окна. Это классическая проблема графической подсистемы при работе через RemoteApp. Когда 1С вызывает модальное окно (особенно устаревшим методом Вопрос()), оно может не получить фокус или отрисоваться «за» основным окном.
Проанализируем ситуацию: основное окно заблокировано, так как ждет ответа, а окно вопроса не видно пользователю. В результате создается полное ощущение зависания. Использование асинхронного метода ПоказатьВопрос() частично решает эту проблему, так как окно создается иными механизмами платформы. Однако если проблема сохраняется, системным администраторам рекомендуется:
DisableHardwareAcceleration=1 в 1CEStart.cfg).Посмотрим на попытку автора обновить форму через ЭтаФорма.Прочитать(). В 1С метод Прочитать() предназначен для того, чтобы перечитать данные объекта из базы данных в память формы. Если вы программно изменили данные в табличной части, но еще не записали документ, вызов Прочитать() просто **удалит** ваши изменения, заменив их теми, что сохранены в базе.
Для корректного обновления интерфейса мы рекомендуем следовать следующим правилам:
ЭтаФорма.ОбновитьОтображениеДанных(). Это заставит платформу перерисовать элементы и обновить связанные условные оформления.Элементы.ИмяСписка.Обновить().ОповеститьОбИзменении().Подводя итог, можно сказать, что «зависания» в 1С чаще всего связаны с попыткой использовать синхронные (модальные) методы там, где архитектура управляемого приложения требует асинхронности.
Проанализируем ключевые моменты:
Вопрос() в управляемых формах. Всегда используйте ПоказатьВопрос() с ОписаниеОповещения.ПриИзменении после вызова ПоказатьВопрос() продолжит выполняться, не дожидаясь ответа пользователя. Логику нужно переносить в процедуру обратного вызова (Callback).ОбновитьОтображениеДанных(), а не Прочитать(), чтобы не потерять введенные пользователем данные.Соблюдение этих принципов позволит создавать отзывчивые интерфейсы, которые будут стабильно работать в любых условиях эксплуатации.