Как поставить паузу в коде 1С: рабочие способы

· 9 мин

Содержание

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

Правильный метод зависит от задачи. Повторить отправку после ошибки, опросить внешний сервис «готов ли ответ», обновлять список на форме раз в минуту, выдержать интервал между запросами к API — это разные сценарии, и способ создать задержку в каждом свой. Ниже — все рабочие методы паузы и приостановки с примерами кода и границами применимости.

Процедура Приостановить: пауза на фиксированное время

Самый прямой способ — глобальная процедура Приостановить (англ. Sleep). Она останавливает текущий поток выполнения на указанное время.

// пауза 2 секунды
Приостановить(2000);

Параметр задаётся в миллисекундах, а не в секундах. Приостановить(1000) — это пауза в одну секунду, Приостановить(500) — полсекунды. Это первая ошибка новичка: поставить Приостановить(5) и ждать пять секунд, а получить паузу в пять тысячных.

Процедура доступна на сервере, в толстом и тонком клиенте. В веб-клиенте её нет — там для отложенного запуска используют обработчик ожидания (о нём ниже).

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

Частый прикладной случай — выдержать интервал между обращениями к внешнему API, который ограничивает частоту запросов. После каждого запроса ставят короткую паузу, чтобы не упереться в лимит и не получить отказ. Делают это на сервере или в фоновом задании: там блокировка потока никому не мешает, а код обмена всё равно выполняется без участия пользователя.

Почему блокирующую паузу не ставят в клиентском коде

Клиентский поток в 1С один и тот же обслуживает и ваш код, и перерисовку окна. Пока работает Приостановить, форма не отвечает: не нажимаются кнопки, не крутится курсор, Windows может показать «Программа не отвечает».

На сервере долгая пауза тоже опасна. Она держит вызов открытым, занимает рабочий процесс и может упереться в таймаут вызова сервера. Не ставьте Приостановить на тысячи итераций цикла и не «спите» минутами в интерактивном серверном вызове.

Где Приостановить уместна:

  • 🔁 короткая выдержка между повторными попытками на сервере (сотни-тысячи миллисекунд);
  • ⚙️ пауза внутри фонового задания, где интерфейса нет;
  • 🧪 отладочные сценарии, когда нужно замедлить выполнение.

На практике безопасны серверные паузы в пределах нескольких секунд, а не минут: чем дольше занят рабочий процесс, тем выше риск упереться в таймаут вызова сервера. Для клиентского кода, где надо «подождать и потом что-то сделать», паузу заменяют таймером.

Таймеры в формах: обработчик ожидания вместо паузы

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

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // обновлять список каждые 60 секунд
    ПодключитьОбработчикОжидания("ОбновитьДанныеФормы", 60);
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьДанныеФормы()
    // код обновления
КонецПроцедуры

Три важных момента по синтаксису:

  1. Первый параметр — имя процедуры строкой, сама процедура должна быть на форме, без параметров.
  2. Интервал задаётся в секундах. Значения больше 1 округляются до целых секунд; дробные интервалы меньше секунды (например, 0.2) тоже допустимы.
  3. Третий параметр Однократно — если передать Истина, обработчик сработает один раз и сам отключится. Это и есть отложенный одноразовый запуск.
&НаКлиенте
Процедура ВыполнитьЧерезТриСекунды()
    // сработает один раз через 3 секунды
    ПодключитьОбработчикОжидания("ОтложенноеДействие", 3, Истина);
КонецПроцедуры

&НаКлиенте
Процедура ОтложенноеДействие()
    // код, который нужно выполнить с задержкой
КонецПроцедуры

Повторяющийся обработчик надо отключать, когда он больше не нужен: ОтключитьОбработчикОжидания("ОбновитьДанныеФормы"). Иначе таймер продолжит дёргать процедуру, пока открыта форма.

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

&НаКлиенте
Процедура ЗапуститьДлиннуюОперацию()
    ИдентификаторЗадания = ЗапуститьНаСервере(); // стартует фоновое задание, возвращает идентификатор
    ПодключитьОбработчикОжидания("ПроверитьГотовность", 2);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьГотовность()
    Если ЗаданиеЗавершеноНаСервере(ИдентификаторЗадания) Тогда
        ОтключитьОбработчикОжидания("ПроверитьГотовность");
        ПоказатьРезультат();
    КонецЕсли;
КонецПроцедуры

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

Обратите внимание на разницу единиц: у Приостановить — миллисекунды, у обработчика ожидания — секунды. Их легко перепутать при переносе кода.

Асинхронное ожидание через оператор Ждать

Иногда «задержка» — это на самом деле «подожди, пока закончится операция», а не «подожди ровно N секунд». Для этого с версии платформы 8.3.18 в языке есть асинхронные методы (ключевое слово Асинх) и оператор Ждать.

Оператор Ждать приостанавливает выполнение асинхронного метода до завершения асинхронной операции и при этом не блокирует интерфейс. Применять его можно только внутри процедуры или функции, объявленной как Асинх.

&НаКлиенте
Асинх Процедура ПроверитьПередЗакрытием()
    Ответ = Ждать ВопросАсинх("Сохранить изменения?", РежимДиалогаВопрос.ДаНет);
    Если Ответ = КодВозвратаДиалога.Да Тогда
        // сохранить данные
    КонецЕсли;
КонецПроцедуры

Здесь строка с Ждать «останавливается» до ответа пользователя, но окно всё это время живое. Так же ждут завершения чтения файла, вызова асинхронного серверного метода и других долгих операций.

Важно не путать: оператор Ждать — это ожидание события, а не фиксированной паузы. Если нужна именно выдержка в N секунд на клиенте, по-прежнему используют обработчик ожидания с параметром Однократно.

Оператор Ждать нельзя поставить в обычной, не асинхронной процедуре — компилятор это не пропустит. Значение, которое возвращает асинхронный метод, имеет тип Обещание, и Ждать как раз разворачивает его в готовый результат. Если один асинхронный метод вызывает другой, ключевое слово Асинх тянут по цепочке до самого верхнего обработчика события формы.

Асинхронный подход постепенно вытесняет старый стиль с процедурами-оповещениями (ОписаниеОповещения и методы вида Начать…). Читается он линейно, сверху вниз, без «лесенки» вложенных колбэков, поэтому новый клиентский код с ожиданием операций пишут именно на Асинх/Ждать, если платформа это позволяет.

Повторные попытки с нарастающей задержкой

Классический сценарий паузы на сервере — повтор операции, которая может временно не удаться: запись при блокировке, обращение к внешнему сервису, отправка в веб-сервис. Между попытками выдерживают растущий интервал, чтобы не долбить ресурс в цикле.

МаксПопыток = 3;
Для Попытка = 1 По МаксПопыток Цикл
    Попытка
        ВыполнитьОперацию();
        Прервать; // успех — выходим из цикла
    Исключение
        Если Попытка = МаксПопыток Тогда
            ВызватьИсключение; // попытки кончились — пробрасываем ошибку
        КонецЕсли;
        // пауза растёт: 1 сек, 2 сек, ...
        Приостановить(1000 * Попытка);
    КонецПопытки;
КонецЦикла;

Разбор логики:

  • при успехе Прервать выходит из цикла сразу;
  • на последней попытке ошибку не глушим, а пробрасываем через ВызватьИсключение;
  • пауза 1000 * Попытка даёт выдержку 1 и 2 секунды между тремя попытками.

Такой цикл с Приостановить держите на сервере или в фоновом задании и всегда ограничивайте число попыток. Бесконечный Пока Истина Цикл с паузой внутри рано или поздно упрётся в таймаут вызова или заблокирует процесс.

Повторять есть смысл только временные сбои: блокировку записи, таймаут сети, кратковременную занятость внешнего сервиса. Ошибки в самих данных — незаполненный реквизит, нарушение бизнес-правила — повтор не исправит, он лишь впустую потратит время и паузы. Если причина известна и не временная, пробрасывайте исключение сразу, без цикла.

Когда повторы идут из многих сеансов одновременно, одинаковая выдержка синхронизирует их и даёт новый всплеск нагрузки на том же такте. Добавьте к паузе небольшой случайный разброс (через генератор случайных чисел), чтобы попытки разных сеансов разъехались по времени.

Паузы в фоновых и регламентных заданиях

Если задержка нужна не разово, а по расписанию, цикл с паузой — неправильный инструмент. Для периодического запуска есть регламентные задания: периодичность задаётся их расписанием (Расписание), интервалы в котором считаются в секундах. Платформа сама запустит задание в нужное время, без «спящего» кода.

Внутри самого фонового задания Приостановить работает нормально — интерфейса там нет, и короткая пауза никому не мешает. Это удобно для выдержки между порциями обработки большого объёма данных.

Отдельная задача — дождаться, пока фоновое задание завершится. Не крутите пустой цикл с паузой, опрашивая статус. У объекта фонового задания есть метод ОжидатьЗавершенияВыполнения, которому передают таймаут ожидания в секундах:

Задание = ФоновыеЗадания.Выполнить("МойМодуль.ДлиннаяОперация", Параметры);
// ждём завершения не дольше 30 секунд
Задание.ОжидатьЗавершенияВыполнения(30);

Метод сам вернёт управление, как только задание закончится или истечёт таймаут. Это надёжнее ручного опроса с Приостановить.

Запустить регламентное задание вне расписания, вручную, можно из консоли заданий или кодом — это удобно при отладке, когда ждать наступления времени по расписанию некогда. А чтобы задание не стартовало повторно, пока предыдущий запуск ещё идёт, у регламентных заданий есть встроенная защита от одновременного выполнения — отдельная пауза для этого не нужна.

Грабли, на которые наступают с паузами

Несколько ситуаций, где задержка ведёт себя не так, как ждёшь:

  • 🔒 Пауза внутри транзакции держит блокировки. Если Приостановить стоит между НачатьТранзакцию и ЗафиксироватьТранзакцию, все наложенные в транзакции блокировки сохраняются всё время паузы, и другие сеансы ждут. Не ставьте паузу внутри открытой транзакции. Сначала фиксируйте транзакцию, потом ждите.
  • ✍️ Обработчик не сработал — опечатка в имени. Имя процедуры передаётся строкой, и платформа не проверяет его при подключении. Ошиблись в названии — таймер просто молча не сработает, без ошибки. Сверяйте имя символ в символ.
  • 🧩 У процедуры-обработчика не должно быть параметров. Если объявить её с параметрами, вызов не состоится. Данные передают через реквизиты формы, а не через аргументы.
  • ♻️ Таймер не отключили — он работает дальше. Повторяющийся обработчик живёт, пока открыта форма. Отключайте его, когда задача выполнена, иначе процедура продолжит вызываться вхолостую.
  • ⏳ Опрос пустым циклом вместо ожидания. Конструкция Пока НЕ Готово Цикл Приостановить(500) КонецЦикла на клиенте вешает окно, а на сервере жжёт процесс. На клиенте опрашивайте статус обработчиком ожидания, на сервере — методом ОжидатьЗавершенияВыполнения.

Какой способ задержки выбрать

Коротко — по задаче:

СпособКогда применятьБлокирует интерфейсГде доступен
Приостановить(мс)короткая пауза на сервере, между попыткамидасервер, толстый и тонкий клиент
ПодключитьОбработчикОжиданиятаймер и отложенный запуск на форменетклиент (в т.ч. веб)
Оператор Ждать (Асинх)ожидание завершения операции на клиентенетклиент, платформа 8.3.18+
Расписание регламентного заданиязапуск по времени и периодическинетсервер
Цикл Попытка + Приостановитьповтор с нарастающей задержкойда (на сервере)сервер, фон

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

Частые вопросы

В каких единицах задаётся пауза в `Приостановить`?
В миллисекундах. Приостановить(1000) — пауза в одну секунду, Приостановить(250) — четверть секунды. Это отличается от обработчика ожидания, где интервал в секундах.
Почему при `Приостановить` зависает окно?
Клиентский поток один: пока идёт блокирующая пауза, он не перерисовывает форму и не реагирует на ввод. На клиенте вместо паузы используйте обработчик ожидания.
Можно ли сделать паузу в веб-клиенте?
Процедура Приостановить в веб-клиенте недоступна. Отложенный или повторяющийся вызов делают через ПодключитьОбработчикОжидания, а ожидание операции — через асинхронный оператор Ждать.
Какой минимальный интервал у обработчика ожидания?
Интервал задаётся в секундах. Значения больше 1 округляются до целых секунд; дробные интервалы меньше секунды (например, 0.2) допустимы.
Как сделать паузу между повторными попытками записи или отправки?
Оберните операцию в Попытка/Исключение в цикле с ограничением числа попыток и ставьте Приостановить между ними. Выполняйте это на сервере или в фоновом задании, а не в клиентском коде.