Программная пауза в 1С: все способы и их риски
Содержание
Пауза на клиенте делается глобальной процедурой Ждать(Секунды) — например, Ждать(2) остановит выполнение на две секунды. На сервере этой процедуры нет: там задержку организуют фоновым заданием, таймаутом внешнего соединения или (в крайнем случае) внешней компонентой. Если нужно не заморозить код, а выполнить что-то позже, не блокируя интерфейс, — это ПодключитьОбработчикОжидания.
Ниже разберём каждый способ: где он работает, какой у него побочный эффект и когда его применять. Сразу предупреждение: «подождать циклом» — самый частый и самый вредный вариант, он грузит процессор впустую. К нему вернёмся отдельно.
Выбрать подходящий механизм под конкретную задачу поможет быстрый разбор:
Ждать(Секунды) — простая блокирующая пауза, годится для скриптов и тестов.Таймаут у соединения.Пауза на клиенте: процедура Ждать
Самый прямой способ сделать задержку в 1С на клиенте — глобальная процедура Ждать:
Ждать(3); // остановить выполнение на 3 секунды
Полная форма вызова — Ждать(<Интервал>, <Интерактивно>):
- 🕒
Интервал— число секунд. Допускаются дробные значения, то естьЖдать(0.5)даст полсекунды. - 👁
Интерактивно— булево, по умолчаниюЛожь. Если передатьИстина, система покажет пользователю индикатор ожидания и даст возможность прервать операцию.
Процедура работает только в клиентском контексте: тонкий клиент, веб-клиент, толстый клиент в режиме управляемого приложения. На сервере и во внешнем соединении её нет — компилятор выдаст ошибку.
Ждать блокирует поток выполнения полностью. Пока идёт пауза, форма не реагирует на действия пользователя: окно «подвисает». Для коротких технических пауз это терпимо, для ожидания в несколько секунд во время работы оператора — нет.
Отдельно стоит Ждать(0). Нулевой интервал паузы не делает, но отдаёт управление системе: обрабатываются накопившиеся события и подключённые обработчики ожидания. Иногда это нужно, чтобы форма «догнала» изменения перед следующим шагом.
Не используйте Ждать внутри транзакции или в серверных вызовах, которые ждёт пользователь: длинная пауза удержит блокировки и повиснет на всех.
Не путайте два разных Ждать. Есть глобальная процедура Ждать(Секунды) — та самая блокирующая пауза из этого раздела. И есть оператор Ждать в асинхронных методах (Асинх Функция ... Ждать ...), который появился в платформе для работы без вложенных обработчиков оповещения. Второй — не про паузу: он не «ждёт N секунд», а дожидается результата асинхронной операции и возвращает управление, не морозя клиент. Если вам нужна именно задержка во времени — это процедура с числовым аргументом.
Как подождать, не морозя интерфейс
Если задача — «выполнить что-то через несколько секунд», а не «остановить код здесь», блокирующая пауза вредна. Правильный инструмент — обработчик ожидания:
// где-то в модуле формы
ПодключитьОбработчикОжидания("ПослеПаузы", 3, Истина);
&НаКлиенте
Процедура ПослеПаузы()
// этот код выполнится через 3 секунды
ОбновитьДанныеНаФорме();
КонецПроцедуры
Параметры — ПодключитьОбработчикОжидания(<ИмяПроцедуры>, <Интервал>, <Однократно>):
- Имя клиентской процедуры без параметров (строкой).
- Интервал в секундах. Минимум — 1 секунда, дробные значения меньше единицы не сработают.
Однократно=Истина— вызвать один раз. ЕслиЛожьили не указано, процедура будет срабатывать по кругу, пока её не отключат.
Ключевая разница с Ждать: обработчик не блокирует форму. Пользователь продолжает работать, а через заданный интервал платформа сама вызовет вашу процедуру. Это способ сделать «задержку» перед повторной попыткой, опросом статуса или автообновлением списка.
Отключается обработчик симметрично:
ОтключитьОбработчикОжидания("ПослеПаузы");
Для периодического опроса (например, «каждые 5 секунд проверяй, готов ли отчёт») обработчик ожидания с Однократно = Ложь — штатное решение. Не делайте опрос циклом с Ждать — это заморозит клиент на всё время ожидания.
Пауза на сервере: почему Ждать недоступен
На сервере процедуры Ждать нет по замыслу платформы. Серверный код выполняется в рабочем процессе кластера и обслуживает много сеансов; заморозить его «на подождать» — значит занять рабочий процесс вхолостую и ухудшить работу всем. Поэтому прямой паузы на сервере платформа не даёт.
Когда задержка на сервере всё-таки нужна, применяют один из обходных путей:
- Внешняя компонента с методом задержки (на базе системного вызова
Sleep). Самый корректный серверный вариант: компонента на Native API вызывает ожидание средствами ОС, не загружая процессор. Минус — её нужно разработать, собрать и зарегистрировать. - Системная команда ОС. Запуск через
ЗапуститьПриложениесинхронной команды, которая сама делает паузу: на Windows этоtimeout /t 5 /nobreak, на Linux —sleep 5. Выглядит это так:
// Windows, синхронный запуск (ждём завершения команды)
ЗапуститьПриложение("cmd /c timeout /t 5 /nobreak", , Истина);
Третий параметр Истина означает «дождаться завершения». Способ рабочий, но требует права на запуск приложений на сервере, зависит от ОС и всё равно блокирует рабочий процесс на время паузы. Используйте его только когда внешнюю компоненту собрать негде.
3. Цикл по времени — busy wait. Простой, но вредный способ, разбираем ниже отдельно.
Прежде чем городить паузу на сервере, остановитесь и спросите: действительно ли нужна именно задержка выполнения? Чаще задача решается иначе — отложенным запуском (фоновое задание) или таймаутом внешнего соединения. Серверная пауза почти всегда признак того, что архитектуру стоит пересмотреть.
Отложенное выполнение: фоновые и регламентные задания
Если смысл задержки — «сделать это потом» или «вынести долгую операцию из основного потока», паузы не нужны вовсе. Нужны задания.
Фоновое задание запускает метод в отдельном сеансе, не блокируя тот, что его инициировал:
Параметры = Новый Массив;
Параметры.Добавить(Ссылка);
ФоновыеЗадания.Выполнить("ОбщийМодуль.ДлиннаяОперация", Параметры);
Запускается оно сразу, а не «через N минут». Инициатор при этом продолжает работу и может периодически проверять состояние задания методами объекта ФоновоеЗадание (например, через ПолучитьФоновыеЗадания с отбором). Это и есть «задержка без задержки»: тяжёлый код уходит в фон, а интерфейс не ждёт.
Регламентное задание — для запуска именно по времени. У него есть расписание (Расписание), где задаются периодичность, время старта, дни недели. Если надо выполнить код «через час» или «каждую ночь в 2:00» — это регламентное задание, а не пауза в коде.
В типовых конфигурациях на БСП для фоновых операций есть подсистема «Длительные операции»: она упаковывает запуск в фоне, прогресс и получение результата. Если конфигурация типовая — используйте её вместо ручной работы с ФоновыеЗадания.
Важно про отладку и окружение:
- Фоновые задания не запускаются в файловой базе, если нет активного клиентского сеанса, — учитывайте при тестировании.
- Параметры метода должны быть сериализуемыми: ссылки, примитивы, структуры из них. Мутабельные объекты формы туда не передать.
Задержка циклом и чем она опасна
Самый частый «народный» способ сделать паузу — крутить пустой цикл, пока не пройдёт нужное время:
// ТАК ДЕЛАТЬ НЕ НАДО
Старт = ТекущаяУниверсальнаяДатаВМиллисекундах();
Пока ТекущаяУниверсальнаяДатаВМиллисекундах() - Старт < 5000 Цикл
// пусто — просто ждём 5 секунд
КонецЦикла;
Работает, но ценой того, что ядро процессора на всё время паузы загружено на 100% впустую. Это busy wait — активное ожидание. Чем он плох:
- 🔥 Нагрузка на CPU. Один такой цикл съедает ядро целиком. Несколько сеансов с таким кодом кладут сервер.
- 🧊 Заморозка. На клиенте форма виснет так же, как при
Ждать, но ещё и греет процессор. На сервере — занимает рабочий процесс. - ⏱ Неточность. Реальная пауза зависит от загрузки машины и может «уехать».
Если альтернатив действительно нет и пауза нужна здесь и сейчас, на клиенте берите Ждать (оно отдаёт ядро системе, а не жжёт его), а на сервере — внешнюю компоненту или системную команду. Пустой цикл — последний вариант, которого стоит избегать.
Отдельно опасен цикл с обращением к базе или сервису «для проверки» на каждой итерации без паузы между запросами. Это не ожидание, а DDoS собственного сервера: тысячи запросов в секунду. Между проверками всегда должен быть интервал.
Таймауты при работе с внешними сервисами
Часто за «задержкой» на самом деле скрывается зависание на внешнем сервисе: код ушёл за данными по HTTP и ждёт ответа, которого нет. Решение здесь не пауза, а таймаут — ограничение времени ожидания.
У объекта HTTPСоединение за это отвечает свойство и параметр конструктора Таймаут (в секундах):
Соединение = Новый HTTPСоединение(
"api.example.ru", 443, , , , 10, Новый ЗащищённоеСоединениеOpenSSL());
Здесь 10 — максимум 10 секунд на операцию. Если сервис не ответил, вы получите ошибку и сможете её обработать, а не повиснете навсегда.
- 🌐 Всегда задавайте таймаут при обращении к внешним сервисам. По умолчанию ожидание может быть неограниченным, и один медленный ответ подвесит сеанс.
- 🔁 Для повторных попыток при сбое делайте паузу между ними — но на клиенте через обработчик ожидания, а в фоновом задании через короткую серверную задержку или просто следующий запуск по расписанию. Полезный приём — наращивать паузу: первая попытка через 2 секунды, вторая через 4, третья через 8. Так вы не заваливаете сервис запросами, пока он восстанавливается.
- 🔌 У веб-сервисных прокси (
WSОпределения,WSПрокси) таймаут задаётся аналогично в параметрах получения определений.
Разделяйте два понятия: таймаут — «сколько максимум ждать ответа», пауза — «подождать заданное время намеренно». Для внешних сервисов почти всегда нужен первый.
Как отладить и замерить код с задержкой
Код с паузами и фоновыми заданиями отлаживается сложнее обычного — часть выполняется не там, где вы его запустили.
Замер фактической паузы. Проверить, сколько реально ждал код, проще всего по времени:
Старт = ТекущаяУниверсальнаяДатаВМиллисекундах();
Ждать(2);
Сообщить("Пауза заняла " + (ТекущаяУниверсальнаяДатаВМиллисекундах() - Старт) + " мс");
Так видно расхождение между запрошенным и реальным интервалом.
Отладка фоновых заданий. Чтобы точки останова срабатывали в коде, который выполняется в фоне, отладку рабочих процессов нужно разрешить:
- В клиент-серверной базе — включить отладку по протоколу (HTTP) и разрешить отладку фоновых заданий в настройках кластера/публикации.
- В конфигураторе — в предмете отладки отметить тип «Фоновые задания», иначе точки останова в них просто не остановят выполнение.
Если точка останова в фоновом задании не срабатывает — почти всегда причина в том, что отладка фоновых заданий не включена, а не в ошибке кода. Проверьте настройку в первую очередь.
Визуализация прогресса. Для долгих операций показывайте пользователю состояние, а не пустое ожидание: индикатор через Состояние(...) на сервере или обновление поля на форме по обработчику ожидания. Так «задержка» перестаёт выглядеть зависанием.
Для точного профилирования (где именно код тратит время) используйте замер производительности в конфигураторе — он покажет длительность каждой строки, включая паузы и обращения к сервисам.
Частые вопросы
Почему процедура Ждать не компилируется на сервере?
Ждать существует только в клиентском контексте. На сервере паузы делают через фоновое задание, таймаут внешнего соединения или внешнюю компоненту. Если вам понадобилась серверная пауза — скорее всего, задачу стоит решить отложенным запуском, а не задержкой.Можно ли сделать паузу меньше секунды?
Ждать(0.3) остановит на 0,3 секунды, интервал может быть дробным. А вот у обработчика ожидания минимум — целая 1 секунда, меньше задать нельзя.Как сделать задержку, не замораживая интерфейс пользователя?
ПодключитьОбработчикОжидания: процедура вызовется через заданное число секунд, а форма всё это время остаётся активной. Блокирующий Ждать для ожидания во время работы оператора не подходит.Фоновое задание стартует сразу — как запустить его позже?
Как избежать зависания при обращении к внешнему сервису?
Таймаут у HTTPСоединения (в секундах). Тогда при отсутствии ответа код получит ошибку через заданное время, а не повиснет. Это надёжнее любой самодельной паузы.