Пауза и задержка выполнения кода в 1С 8.3
Содержание
В 1С нет глобальной команды Sleep, которая просто остановила бы код на N секунд, — и это сделано намеренно. Клиентский код выполняется в один поток: блокирующая пауза заморозит интерфейс, а на тонком и веб-клиенте может оборвать сеанс. Поэтому «паузу» в 1С делают одним из трёх способов в зависимости от того, что именно нужно.
Если нужно отложить действие на клиенте — используют ПодключитьОбработчикОжидания. Если нужно дождаться результата долгой операции — запускают фоновое задание и ждут его завершения. Если нужно остановить код построчно, чтобы посмотреть значения, — ставят точку останова в отладчике. Разберём каждый случай с кодом и путями меню.
Почему готовой команды Sleep нет и чем её заменить
Платформа 1С:Предприятие 8.3 событийная. Форма реагирует на действия пользователя, фоновые процессы живут отдельно, а длинная блокировка потока ломает эту модель. Жёсткое «усни на 5 секунд» в клиенте приводит к зависшему окну и сообщению «Приложение не отвечает».
Поэтому вместо паузы платформа предлагает отложенный вызов: вы говорите «через столько-то секунд выполни вот эту процедуру», а управление сразу возвращается платформе. Пользователь продолжает работать, а по таймеру срабатывает ваш код.
Правило простое: нужна задержка на клиенте — думайте не «как усыпить код», а «какую процедуру запустить по таймеру». Это и есть идеология 1С.
В платформе 8.3 с номером не ниже 8.3.18 для ожидания результата асинхронных операций появился более аккуратный приём — асинхронные методы и ключевое слово Ждать. Оно приостанавливает выполнение асинхронной функции до готовности результата, но не блокирует клиента: пока функция «ждёт», интерфейс остаётся живым. Если ваша конфигурация работает на такой платформе, это читается проще, чем цепочки оповещений. На более ранних сборках остаётся классический обработчик ожидания — его и разберём первым, он доступен везде.
Обработчик ожидания: пауза без заморозки клиента
Основной инструмент паузы на клиенте — ПодключитьОбработчикОжидания. Метод доступен в тонком, толстом и веб-клиенте, работает одинаково.
Синтаксис:
ПодключитьОбработчикОжидания(<ИмяПроцедуры>, <Интервал>, <Однократно>);
ИмяПроцедуры— имя экспортной процедуры без параметров (в модуле формы или модуле команды);Интервал— время до вызова в секундах, допустимо дробное значение;Однократно— еслиИстина, процедура сработает один раз и обработчик отключится сам.
Пример: показать сообщение через 3 секунды после открытия формы.
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ПодключитьОбработчикОжидания("ПоказатьПодсказку", 3, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ПоказатьПодсказку()
Сообщить("Прошло 3 секунды с момента открытия формы");
КонецПроцедуры
Если обработчик не одноразовый, он будет срабатывать каждые N секунд, пока вы его не остановите:
ОтключитьОбработчикОжидания("ПоказатьПодсказку");
Не задавайте интервал в доли секунды для постоянно повторяющихся обработчиков — частый опрос нагружает клиента и канал связи, особенно в веб-клиенте. Для периодических задач разумный минимум — 1–2 секунды.
Обработчик ожидания закрывает большинство задач, где раньше хотелось «паузу»: дать анимации проиграться, дождаться, пока пользователь перестанет печатать, отложить тяжёлый расчёт на момент после отрисовки формы.
Жёсткая задержка в толстом клиенте и её риски
Иногда всё же нужна именно блокирующая задержка — например, в обработке, которая запускается в толстом клиенте под Windows и ни с кем не взаимодействует. Готовой функции в платформе нет, но её имитируют через COM-объект операционной системы.
Оболочка = Новый COMObject("WScript.Shell");
// windowStyle = 0 (скрыто), waitOnReturn = Истина (ждать завершения)
Оболочка.Run("timeout /t 5 /nobreak", 0, Истина);
Команда timeout оболочки Windows «спит» 5 секунд, а 1С ждёт её завершения, потому что третий параметр Run равен Истина.
Этот приём блокирует поток целиком: окно 1С перестаёт отвечать на всё время паузы. Он допустим только в толстом клиенте под Windows и только для коротких служебных задержек. В тонком и веб-клиенте так делать нельзя — сеанс может разорваться по таймауту.
Поэтому для интерфейсных сценариев возвращайтесь к обработчику ожидания: он решает ту же задачу, не морозя окно.
Как подождать на сервере завершения внешнего процесса
На сервере задача «паузы» звучит иначе: обычно нужно не просто подождать, а дождаться результата долгой операции — выгрузки файла, ответа веб-сервиса, пересчёта итогов. Правильный путь — вынести операцию в фоновое задание и ждать его завершения.
Задание = ФоновыеЗадания.Выполнить(
"ОбщийМодуль.ДлинныйРасчёт",
Новый Массив,
,
"Пересчёт остатков");
// Ждём завершения не дольше 30 секунд
Задание.ОжидатьЗавершенияВыполнения(30);
Если Задание.Состояние = СостояниеФоновогоЗадания.Завершено Тогда
Сообщить("Расчёт выполнен");
КонецЕсли;
Метод ожидания у объекта фонового задания в современных сборках платформы 8.3 называется ОжидатьЗавершенияВыполнения(Таймаут); в более ранних сборках — ОжидатьЗавершения(Таймаут). Таймаут задаётся в секундах; если его не указать, вызов будет ждать до самого конца задания.
Несколько правил, чтобы не наступить на грабли:
- 🔸 Ожидание нельзя вызывать внутри открытой транзакции — задание в другом сеансе её не увидит, и вы рискуете получить взаимоблокировку.
- 🔸 После таймаута проверяйте
Состояние: задание может быть ещёАктивно. Не считайте, что оно завершилось, только потому что вызов вернул управление. - 🔸 Busy-wait — цикл с проверкой
ТекущаяДатаСеанса()— на сервере не используйте: он намертво занимает рабочий процесс и лицензию, ничего при этом не делая.
Если операцию запустили с клиента, удобнее не держать серверный вызов, а опрашивать состояние задания с клиента по таймеру — тем самым обработчиком ожидания из раздела выше. Так пользователь видит отзывчивую форму, а код «ждёт» фоновую операцию короткими проверками:
&НаКлиенте
Процедура ЗапуститьОперацию(Команда)
ИдентификаторЗадания = ЗапуститьНаСервере(); // вернёт УникальныйИдентификатор задания
ПодключитьОбработчикОжидания("ПроверитьЗадание", 2);
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьЗадание()
Если ЗаданиеЗавершеноНаСервере(ИдентификаторЗадания) Тогда
ОтключитьОбработчикОжидания("ПроверитьЗадание");
Сообщить("Операция завершена");
КонецЕсли;
КонецПроцедуры
Каждые 2 секунды клиент спрашивает сервер, готово ли задание, и отключает опрос, как только получает ответ. Это стандартный шаблон «длительной операции» в типовых конфигурациях.
Точки останова: приостановка кода при отладке
Когда «пауза» нужна не в рабочем сценарии, а чтобы остановить код и посмотреть переменные, — это задача отладчика. Точка останова ставит код на паузу на конкретной строке.
Как поставить и запустить отладку в Конфигураторе:
- Откройте нужный модуль, встаньте на строку и нажмите
F9— слева появится красный маркер точки останова. - Запустите отладку: меню
Отладка → Начать отладкуили клавишаF5. - Когда исполнение дойдёт до вашей строки, оно остановится, не выполнив её.
Дальше код «ведут» вручную горячими клавишами:
| Клавиша | Действие |
|---|---|
F5 | Продолжить выполнение до следующей точки останова |
F10 | Шагнуть через (выполнить строку, не заходя в процедуру) |
F11 | Шагнуть внутрь (зайти в вызываемую процедуру) |
Shift+F11 | Выйти из текущей процедуры |
Shift+F9 | Вычислить выражение под курсором |
Полезные приёмы на паузе:
- 🔹 Точка останова с условием. Щёлкните маркер правой кнопкой и задайте условие — код встанет, только когда оно истинно. Незаменимо, когда цикл делает тысячи итераций, а поймать надо одну.
- 🔹 Табло. Окно для просмотра и слежения за значениями переменных во время паузы.
- 🔹 Остановка по ошибке. В меню
Отладкаможно включить автоматическую остановку в момент возникновения исключения — код сам встанет там, где упал.
Чтобы отладчик вообще подключался к запускаемому сеансу, в Конфигураторе откройте Сервис → Параметры → Запуск 1С:Предприятия → Отладка и включите установку режима разрешения отладки. Тогда сеанс 1С:Предприятия, запущенный из Конфигуратора, будет виден отладчику.
Для клиент-серверной базы отладку серверного кода нужно заранее разрешить на уровне информационной базы — параметром отладки в консоли кластера или при публикации на веб-сервере. Если это не сделано, точки останова в серверных процедурах просто не сработают, а клиентские — будут. Отладчик подключается к рабочим процессам по сети, поэтому на закрытом контуре проверьте, что соответствующие порты доступны.
COM-объекты и внешние компоненты: ожидание ответа
Отдельная тема — пауза при работе с внешним миром: COM-объектами и внешними компонентами.
Вызовы методов COM-объекта синхронны: 1С сама ждёт, пока метод вернёт управление. Специально «ставить паузу» не нужно — платформа остановится на строке вызова до ответа. Отсюда и подвох: если внешнее приложение зависло, зависнет и ваш сеанс. Поэтому для COM-вызовов, которые могут долго не отвечать, либо выносите их в фоновое задание, либо работайте через толстый клиент, где блокировка интерфейса не оборвёт сеанс.
С внешними компонентами модель другая. Асинхронная компонента не блокирует код, а сообщает о готовности через механизм внешнего события. Вы не «ждёте в цикле», а обрабатываете событие, когда оно придёт:
&НаКлиенте
Процедура ОбработкаВнешнегоСобытия(Источник, Событие, Данные)
Если Событие = "ГотовоеЗначение" Тогда
Сообщить("Компонента вернула: " + Данные);
КонецЕсли;
КонецПроцедуры
Смысл тот же, что и с обработчиком ожидания: вместо остановки потока вы реагируете на сигнал извне. Код не спит — он ждёт события.
Если внешняя компонента возвращает результат не событием, а значением свойства, которое заполняется не сразу, — не крутите пустой цикл «пока свойство не заполнится». Такой опрос займёт процессор и всё равно не отдаст управление платформе. Повесьте на проверку свойства обработчик ожидания с интервалом в секунду: клиент будет периодически заглядывать в компоненту, не блокируя интерфейс.
Задержки внутри циклов и пакетной обработки
Последний частый случай — пауза в длинном цикле: при выгрузке во внешнюю систему, рассылке, обращениях к API «через паузу», чтобы не превысить лимит запросов.
Здесь важно развести две ситуации:
Нужно дать пользователю прервать долгий цикл. На клиенте вставьте в тело цикла вызов:
Для Каждого Строка Из ТаблицаДанных Цикл
ОбработкаПрерыванияПользователя();
// ... тяжёлая обработка строки ...
КонецЦикла;
ОбработкаПрерыванияПользователя() проверяет, не нажал ли пользователь прерывание (Ctrl+Break), и аккуратно останавливает выполнение. Это не пауза, но именно её часто ищут, когда цикл «не отдаёт управление».
Нужна задержка между итерациями (например, пауза между запросами к внешнему сервису). Не делайте блокирующий сон внутри серверного цикла — он держит рабочий процесс. Вместо этого:
- 🔸 если операция идёт на клиенте — обрабатывайте порции по таймеру через обработчик ожидания: одна пачка за вызов, следующая — через заданный интервал;
- 🔸 если операция серверная и объёмная — оформите её как фоновое задание, а при необходимости регулярного запуска используйте регламентное задание с нужным расписанием.
Паузу между запросами к API почти всегда можно заменить правильным размером пакета. Отправляйте данные партиями по расписанию, а не по одному элементу с задержкой — это и быстрее, и не нагружает сервер лишними ожиданиями.
Какой способ паузы выбрать
Короткий ориентир под вашу задачу:
ПодключитьОбработчикОжидания(ИмяПроцедуры, Интервал, Однократно) — работает в тонком, толстом и веб-клиенте, не морозит окно.ОжидатьЗавершенияВыполнения(Таймаут). Операцию выносим в фон, по таймауту проверяем состояние.F9) в Конфигураторе, запуск отладки F5, шаги F10/F11.WScript.Shell с командой timeout. Только локально, блокирует интерфейс.Частые вопросы
Есть ли в 1С функция Sleep или Wait, как в других языках?
ПодключитьОбработчикОжидания на клиенте и ожидание фонового задания на сервере. Блокирующую задержку в толстом клиенте имитируют через COM-объект операционной системы.Минимальный интервал у обработчика ожидания?
Почему точка останова на сервере не срабатывает?
Как остановить зависший цикл, если паузу не ставил?
ОбработкаПрерыванияПользователя() — тогда выполнение можно прервать сочетанием Ctrl+Break. Без этого вызова платформа не проверяет прерывание и цикл не отдаёт управление.