Как сделать паузу или задержку выполнения кода в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С с внешними веб-сервисами и REST API разработчики часто сталкиваются с жесткими лимитами на частоту обращений (Rate Limiting). Например, сервис может разрешать отправку не более одного запроса в несколько секунд. В таких ситуациях возникает необходимость принудительно приостановить выполнение программного кода на определенный интервал времени перед отправкой следующего пакета данных.

В платформе 1С:Предприятие нет универсальной встроенной функции Сон() или Sleep(), однако существует несколько способов реализовать задержку как на стороне клиента, так и на стороне сервера. Разберем основные варианты реализации, их плюсы, минусы и особенности применения.

Способ 1. Цикл ожидания по текущей дате (Busy-wait)

Самый простой и быстрый способ организовать задержку прямо внутри алгоритма или цикла обработки данных — использовать цикл ожидания по системному времени.

Посмотрим на пример реализации паузы длительностью 3 секунды:


Старт = ТекущаяДата();
Пока ТекущаяДата() - Старт < 3 Цикл
    // Пустой цикл ожидания
КонецЦикла;

Разберем, как применить этот подход при циклическом обращении к внешнему сервису:


Для Каждого Стр Из ТаблицаОтправок Цикл
    // Выполняем обращение к сервису
    РезультатЗапросаHTTP = Соединение.Получить(ОбъектHTTPЗапрос);
    
    // Обрабатываем ответ
    ОбработатьОтвет(РезультатЗапросаHTTP);
    
    // Делаем задержку перед следующим запросом к API
    Старт = ТекущаяДата();
    Пока ТекущаяДата() - Старт < 3 Цикл
        // Ожидание завершения 3 секунд
    КонецЦикла;
КонецЦикла;

Проанализируем особенности и недостатки данного метода:

  1. Нагрузка на процессор: Пустой цикл проверки даты заставляет ядро процессора непрерывно выполнять итерации на 100% мощности. Если такой код выполняется на сервере для нескольких пользователей, это может существенно снизить общую производительность системы.
  2. Зависание интерфейса: При выполнении на клиенте окно приложения 1С переходит в состояние «Не отвечает» на время работы цикла.
  3. Точность интервала: Функция ТекущаяДата() возвращает время с точностью до секунды, поэтому фактическая длительность задержки может колебаться в диапазоне от 2,001 до 3,999 секунд.

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

Способ 2. Использование обработчика ожидания на клиенте

Для клиентского контекста управляемых и обычных форм правильным архитектурным решением является использование процедуры ПодключитьОбработчикОжидания(). Это позволяет разделить выполнение длительного процесса на порции без блокировки пользовательского интерфейса.

Разберем по шагам, как настроить периодический вызов процедуры:


&НаКлиенте
Процедура ЗапуститьОбработку()
    // Подключаем однократный вызов процедуры через 3 секунды
    ПодключитьОбработчикОжидания("ВыполнитьШагОбработки", 3, Истина);
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьШагОбработки()
    // Выполняем один шаг запроса к API
    ВыполнитьЗапросКСервису();
    
    // Если остались необработанные данные, планируем следующий вызов
    Если ЕстьДанныеДляОбработки() Тогда
        ПодключитьОбработчикОжидания("ВыполнитьШагОбработки", 3, Истина);
    Иначе
        ПоказатьОповещениеПользователю("Обработка завершена");
    КонецЕсли;
КонецПроцедуры

Особенности метода:

  1. Интерфейс программы не блокируется, пользователь может продолжать работу в других окнах.
  2. Метод ПодключитьОбработчикОжидания() доступен только на клиенте и не может быть вызван в серверном модуле или в фоновом задании.

Способ 3. Серверная пауза через ожидание фонового задания

Для серверного кода в конфигурациях на платформе 1С:Предприятие 8.3 можно использовать механизм ожидания завершения фоновых заданий. Метод ФоновыеЗадания.ОжидатьЗавершения() принимает массив заданий и таймаут ожидания в секундах, переводя текущий поток сервера в режим сна без загрузки процессора.

Посмотрим на пример реализации универсальной функции паузы:


&НаСервере
Процедура СделатьПаузу(ВремяВСекундах)
    ПустойМассивЗаданий = Новый Массив;
    Попытка
        // Метод приостанавливает поток на указанное время
        ФоновыеЗадания.ОжидатьЗавершения(ПустойМассивЗаданий, ВремяВСекундах);
    Исключение
        // Перехват возможного исключения по истечении таймаута
    КонецПопытки;
КонецПроцедуры

Преимущества этого способа:

  1. Работает в серверном контексте, включая регламентные и фоновые задания.
  2. Не создает паразитной нагрузки на CPU (поток находится в состоянии ожидания).
  3. Не требует вызова сторонних утилит операционной системы.

Способ 4. Вызов системных утилит задержки через ЗапуститьПриложение

Еще один способ организации паузы без загрузки процессора — синхронный запуск консольной команды операционной системы с параметром ожидания завершения.

Рассмотрим пример кода для операционных систем Windows и Linux:


&НаСервереИлиНаКлиенте
Процедура ПаузаОС(Секунды)
    // Для Windows используем утилиту timeout или ping
    Команда = "timeout /t " + Формат(Секунды, "ЧГ=0") + " /nobreak";
    
    // Для Linux можно использовать: Команда = "sleep " + Формат(Секунды, "ЧГ=0");
    
    ЗапуститьПриложение(Команда, , Истина);
КонецПроцедуры

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

Рекомендации по оптимизации работы с HTTP-запросами в цикле

При циклической отправке запросов к внешним сервисам обратим внимание на типичные ошибки и рекомендации по их устранению:

  1. Переиспользование объекта HTTPСоединение: Не создавайте экземпляр Новый HTTPСоединение внутри каждой итерации цикла. Инициализируйте соединение один раз перед началом цикла, а внутри цикла создавайте только объекты HTTPЗапрос. Это избавит систему от повторных процедур установки TCP-соединения и TLS-рукопожатия.
  2. Корректное разделение адреса и пути: В конструктор HTTPСоединение передавайте только доменное имя сервера (например, "api.laposte.fr"), а путь к конкретному ресурсу (например, "/suivi/v1/track") указывайте в конструкторе HTTPЗапрос.
  3. Обработка кода ответа 429 (Too Many Requests): Обязательно проверяйте свойство КодСостояния ответа. Если сервис возвращает код 429, значит лимит запросов был превышен. В этом случае следует прочитать заголовок ответа Retry-After, выполнить паузу на указанное сервером время и повторить отправку запроса.
← На главную