Как поставить паузу в коде 1С: рабочие способы
Содержание
Пауза в коде 1С ставится процедурой Приостановить — она останавливает выполнение на заданное число миллисекунд. Но на клиенте такая задержка замораживает интерфейс, поэтому в формах применяют обработчик ожидания, а для длинных операций — фоновые задания и асинхронный код.
Правильный метод зависит от задачи. Повторить отправку после ошибки, опросить внешний сервис «готов ли ответ», обновлять список на форме раз в минуту, выдержать интервал между запросами к API — это разные сценарии, и способ создать задержку в каждом свой. Ниже — все рабочие методы паузы и приостановки с примерами кода и границами применимости.
Процедура Приостановить: пауза на фиксированное время
Самый прямой способ — глобальная процедура Приостановить (англ. Sleep). Она останавливает текущий поток выполнения на указанное время.
// пауза 2 секунды
Приостановить(2000);
Параметр задаётся в миллисекундах, а не в секундах. Приостановить(1000) — это пауза в одну секунду, Приостановить(500) — полсекунды. Это первая ошибка новичка: поставить Приостановить(5) и ждать пять секунд, а получить паузу в пять тысячных.
Процедура доступна на сервере, в толстом и тонком клиенте. В веб-клиенте её нет — там для отложенного запуска используют обработчик ожидания (о нём ниже).
Пауза синхронная и блокирующая: пока она идёт, поток ничего больше не делает. На сервере это нормально для короткой выдержки внутри фоновой операции. На клиенте — почти всегда ошибка.
Частый прикладной случай — выдержать интервал между обращениями к внешнему API, который ограничивает частоту запросов. После каждого запроса ставят короткую паузу, чтобы не упереться в лимит и не получить отказ. Делают это на сервере или в фоновом задании: там блокировка потока никому не мешает, а код обмена всё равно выполняется без участия пользователя.
Почему блокирующую паузу не ставят в клиентском коде
Клиентский поток в 1С один и тот же обслуживает и ваш код, и перерисовку окна. Пока работает Приостановить, форма не отвечает: не нажимаются кнопки, не крутится курсор, Windows может показать «Программа не отвечает».
На сервере долгая пауза тоже опасна. Она держит вызов открытым, занимает рабочий процесс и может упереться в таймаут вызова сервера. Не ставьте Приостановить на тысячи итераций цикла и не «спите» минутами в интерактивном серверном вызове.
Где Приостановить уместна:
- 🔁 короткая выдержка между повторными попытками на сервере (сотни-тысячи миллисекунд);
- ⚙️ пауза внутри фонового задания, где интерфейса нет;
- 🧪 отладочные сценарии, когда нужно замедлить выполнение.
На практике безопасны серверные паузы в пределах нескольких секунд, а не минут: чем дольше занят рабочий процесс, тем выше риск упереться в таймаут вызова сервера. Для клиентского кода, где надо «подождать и потом что-то сделать», паузу заменяют таймером.
Таймеры в формах: обработчик ожидания вместо паузы
На форме отложенные и повторяющиеся действия делает связка ПодключитьОбработчикОжидания / ОтключитьОбработчикОжидания. Это не блокировка: платформа просто вызовет вашу процедуру через заданный интервал, а до тех пор форма работает как обычно.
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// обновлять список каждые 60 секунд
ПодключитьОбработчикОжидания("ОбновитьДанныеФормы", 60);
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьДанныеФормы()
// код обновления
КонецПроцедуры
Три важных момента по синтаксису:
- Первый параметр — имя процедуры строкой, сама процедура должна быть на форме, без параметров.
- Интервал задаётся в секундах. Значения больше 1 округляются до целых секунд; дробные интервалы меньше секунды (например,
0.2) тоже допустимы. - Третий параметр
Однократно— если передатьИстина, обработчик сработает один раз и сам отключится. Это и есть отложенный одноразовый запуск.
&НаКлиенте
Процедура ВыполнитьЧерезТриСекунды()
// сработает один раз через 3 секунды
ПодключитьОбработчикОжидания("ОтложенноеДействие", 3, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ОтложенноеДействие()
// код, который нужно выполнить с задержкой
КонецПроцедуры
Повторяющийся обработчик надо отключать, когда он больше не нужен: ОтключитьОбработчикОжидания("ОбновитьДанныеФормы"). Иначе таймер продолжит дёргать процедуру, пока открыта форма.
Самый полезный приём на этой связке — опрос долгой операции без заморозки окна. Клиент запускает операцию в фоне, а обработчик ожидания раз в пару секунд проверяет, закончилась ли она:
&НаКлиенте
Процедура ЗапуститьДлиннуюОперацию()
ИдентификаторЗадания = ЗапуститьНаСервере(); // стартует фоновое задание, возвращает идентификатор
ПодключитьОбработчикОжидания("ПроверитьГотовность", 2);
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьГотовность()
Если ЗаданиеЗавершеноНаСервере(ИдентификаторЗадания) Тогда
ОтключитьОбработчикОжидания("ПроверитьГотовность");
ПоказатьРезультат();
КонецЕсли;
КонецПроцедуры
Пока задание считается на сервере, пользователь видит живую форму и может её закрыть. Это стандартный способ «ждать» на клиенте долгую обработку: не блокирующая пауза, а периодическая проверка статуса. Платформенная библиотека «Длительные операции» строит индикатор прогресса ровно на этой схеме.
Обратите внимание на разницу единиц: у Приостановить — миллисекунды, у обработчика ожидания — секунды. Их легко перепутать при переносе кода.
Асинхронное ожидание через оператор Ждать
Иногда «задержка» — это на самом деле «подожди, пока закончится операция», а не «подожди ровно N секунд». Для этого с версии платформы 8.3.18 в языке есть асинхронные методы (ключевое слово Асинх) и оператор Ждать.
Оператор Ждать приостанавливает выполнение асинхронного метода до завершения асинхронной операции и при этом не блокирует интерфейс. Применять его можно только внутри процедуры или функции, объявленной как Асинх.
&НаКлиенте
Асинх Процедура ПроверитьПередЗакрытием()
Ответ = Ждать ВопросАсинх("Сохранить изменения?", РежимДиалогаВопрос.ДаНет);
Если Ответ = КодВозвратаДиалога.Да Тогда
// сохранить данные
КонецЕсли;
КонецПроцедуры
Здесь строка с Ждать «останавливается» до ответа пользователя, но окно всё это время живое. Так же ждут завершения чтения файла, вызова асинхронного серверного метода и других долгих операций.
Важно не путать: оператор Ждать — это ожидание события, а не фиксированной паузы. Если нужна именно выдержка в N секунд на клиенте, по-прежнему используют обработчик ожидания с параметром Однократно.
Оператор Ждать нельзя поставить в обычной, не асинхронной процедуре — компилятор это не пропустит. Значение, которое возвращает асинхронный метод, имеет тип Обещание, и Ждать как раз разворачивает его в готовый результат. Если один асинхронный метод вызывает другой, ключевое слово Асинх тянут по цепочке до самого верхнего обработчика события формы.
Асинхронный подход постепенно вытесняет старый стиль с процедурами-оповещениями (ОписаниеОповещения и методы вида Начать…). Читается он линейно, сверху вниз, без «лесенки» вложенных колбэков, поэтому новый клиентский код с ожиданием операций пишут именно на Асинх/Ждать, если платформа это позволяет.
Повторные попытки с нарастающей задержкой
Классический сценарий паузы на сервере — повтор операции, которая может временно не удаться: запись при блокировке, обращение к внешнему сервису, отправка в веб-сервис. Между попытками выдерживают растущий интервал, чтобы не долбить ресурс в цикле.
МаксПопыток = 3;
Для Попытка = 1 По МаксПопыток Цикл
Попытка
ВыполнитьОперацию();
Прервать; // успех — выходим из цикла
Исключение
Если Попытка = МаксПопыток Тогда
ВызватьИсключение; // попытки кончились — пробрасываем ошибку
КонецЕсли;
// пауза растёт: 1 сек, 2 сек, ...
Приостановить(1000 * Попытка);
КонецПопытки;
КонецЦикла;
Разбор логики:
- при успехе
Прерватьвыходит из цикла сразу; - на последней попытке ошибку не глушим, а пробрасываем через
ВызватьИсключение; - пауза
1000 * Попыткадаёт выдержку 1 и 2 секунды между тремя попытками.
Такой цикл с Приостановить держите на сервере или в фоновом задании и всегда ограничивайте число попыток. Бесконечный Пока Истина Цикл с паузой внутри рано или поздно упрётся в таймаут вызова или заблокирует процесс.
Повторять есть смысл только временные сбои: блокировку записи, таймаут сети, кратковременную занятость внешнего сервиса. Ошибки в самих данных — незаполненный реквизит, нарушение бизнес-правила — повтор не исправит, он лишь впустую потратит время и паузы. Если причина известна и не временная, пробрасывайте исключение сразу, без цикла.
Когда повторы идут из многих сеансов одновременно, одинаковая выдержка синхронизирует их и даёт новый всплеск нагрузки на том же такте. Добавьте к паузе небольшой случайный разброс (через генератор случайных чисел), чтобы попытки разных сеансов разъехались по времени.
Паузы в фоновых и регламентных заданиях
Если задержка нужна не разово, а по расписанию, цикл с паузой — неправильный инструмент. Для периодического запуска есть регламентные задания: периодичность задаётся их расписанием (Расписание), интервалы в котором считаются в секундах. Платформа сама запустит задание в нужное время, без «спящего» кода.
Внутри самого фонового задания Приостановить работает нормально — интерфейса там нет, и короткая пауза никому не мешает. Это удобно для выдержки между порциями обработки большого объёма данных.
Отдельная задача — дождаться, пока фоновое задание завершится. Не крутите пустой цикл с паузой, опрашивая статус. У объекта фонового задания есть метод ОжидатьЗавершенияВыполнения, которому передают таймаут ожидания в секундах:
Задание = ФоновыеЗадания.Выполнить("МойМодуль.ДлиннаяОперация", Параметры);
// ждём завершения не дольше 30 секунд
Задание.ОжидатьЗавершенияВыполнения(30);
Метод сам вернёт управление, как только задание закончится или истечёт таймаут. Это надёжнее ручного опроса с Приостановить.
Запустить регламентное задание вне расписания, вручную, можно из консоли заданий или кодом — это удобно при отладке, когда ждать наступления времени по расписанию некогда. А чтобы задание не стартовало повторно, пока предыдущий запуск ещё идёт, у регламентных заданий есть встроенная защита от одновременного выполнения — отдельная пауза для этого не нужна.
Грабли, на которые наступают с паузами
Несколько ситуаций, где задержка ведёт себя не так, как ждёшь:
- 🔒 Пауза внутри транзакции держит блокировки. Если
Приостановитьстоит междуНачатьТранзакциюиЗафиксироватьТранзакцию, все наложенные в транзакции блокировки сохраняются всё время паузы, и другие сеансы ждут. Не ставьте паузу внутри открытой транзакции. Сначала фиксируйте транзакцию, потом ждите. - ✍️ Обработчик не сработал — опечатка в имени. Имя процедуры передаётся строкой, и платформа не проверяет его при подключении. Ошиблись в названии — таймер просто молча не сработает, без ошибки. Сверяйте имя символ в символ.
- 🧩 У процедуры-обработчика не должно быть параметров. Если объявить её с параметрами, вызов не состоится. Данные передают через реквизиты формы, а не через аргументы.
- ♻️ Таймер не отключили — он работает дальше. Повторяющийся обработчик живёт, пока открыта форма. Отключайте его, когда задача выполнена, иначе процедура продолжит вызываться вхолостую.
- ⏳ Опрос пустым циклом вместо ожидания. Конструкция
Пока НЕ Готово Цикл Приостановить(500) КонецЦиклана клиенте вешает окно, а на сервере жжёт процесс. На клиенте опрашивайте статус обработчиком ожидания, на сервере — методомОжидатьЗавершенияВыполнения.
Какой способ задержки выбрать
Коротко — по задаче:
| Способ | Когда применять | Блокирует интерфейс | Где доступен |
|---|---|---|---|
Приостановить(мс) | короткая пауза на сервере, между попытками | да | сервер, толстый и тонкий клиент |
ПодключитьОбработчикОжидания | таймер и отложенный запуск на форме | нет | клиент (в т.ч. веб) |
Оператор Ждать (Асинх) | ожидание завершения операции на клиенте | нет | клиент, платформа 8.3.18+ |
| Расписание регламентного задания | запуск по времени и периодически | нет | сервер |
Цикл Попытка + Приостановить | повтор с нарастающей задержкой | да (на сервере) | сервер, фон |
Правило простое: на клиенте — обработчик ожидания или асинхронный Ждать, на сервере и в фоне — Приостановить короткими интервалами, по расписанию — регламентное задание.
Частые вопросы
В каких единицах задаётся пауза в `Приостановить`?
Приостановить(1000) — пауза в одну секунду, Приостановить(250) — четверть секунды. Это отличается от обработчика ожидания, где интервал в секундах.Почему при `Приостановить` зависает окно?
Можно ли сделать паузу в веб-клиенте?
Приостановить в веб-клиенте недоступна. Отложенный или повторяющийся вызов делают через ПодключитьОбработчикОжидания, а ожидание операции — через асинхронный оператор Ждать.Какой минимальный интервал у обработчика ожидания?
0.2) допустимы.Как сделать паузу между повторными попытками записи или отправки?
Попытка/Исключение в цикле с ограничением числа попыток и ставьте Приостановить между ними. Выполняйте это на сервере или в фоновом задании, а не в клиентском коде.