Как программно сделать паузу при исполнении кода в 1С без нагрузки на процессор

Программист IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С программисты часто сталкиваются с необходимостью искусственно приостановить выполнение алгоритма. Это может потребоваться при обмене данными (ожидание освобождения ресурса), при выполнении запросов к сторонним API, чтобы соблюсти лимиты, или для предотвращения чрезмерной нагрузки на оборудование. Основная сложность заключается в том, чтобы сделать паузу «чистой»: она не должна загружать ядро процессора на 100%, не должна вызывать лишних звуковых сигналов или назойливых окон, мешающих пользователю. Проанализируем существующие решения и выберем наиболее эффективные для версий 7.7 и 8.x.

Проблема стандартных подходов

Разберем ситуацию, когда разработчик пытается реализовать паузу через пустой цикл или проверку времени. В 1С 7.7 часто использовали методы _getPerformanceCounter() или ТекущееВремя(). Рассмотрим пример такого кода:


// Пример кода, который нагружает процессор
Пока (СчетчикВремени2 - СчетчикВремени1) / 1000 < 5 Цикл
    СчетчикВремени2 = _getPerformanceCounter();
КонецЦикла;

Выясним причину, почему это плохо. Несмотря на то, что код выполняет свою задачу, он заставляет одно ядро процессора работать на полную мощность, совершая миллионы бесполезных итераций. Если база работает в терминальном режиме, это замедлит работу всех пользователей сервера. Метод с использованием команды Предупреждение() с таймаутом, напротив, не нагружает CPU, но раздражает пользователя всплывающим окном и звуковым сигналом системы.

Решение 1: Использование системных команд через WScript.Shell

Один из самых популярных и надежных способов — использование объекта WScript.Shell. Рассмотрим вариант с использованием команды ping. Суть метода заключается в отправке запроса на локальный адрес, где время ожидания ответа и будет нашей паузой. Проанализируем реализацию для 1С 8.x:


Процедура Пауза(КоличествоСекунд)
    Shell = Новый COMОбъект("WScript.Shell");
    // Параметр -n задает количество пакетов (секунд)
    Shell.Run("ping 127.0.0.1 -n " + Строка(КоличествоСекунд + 1), 0, Истина);
КонецПроцедуры

В данном коде параметр 0 скрывает окно консоли, а Истина заставляет 1С ждать завершения выполнения команды. Этот метод универсален и отлично подходит как для 7.7, так и для 8.x. Важный нюанс: команда ping отправляет пакеты с интервалом в 1 секунду, поэтому точность до миллисекунд здесь недоступна.

Для более современных версий Windows (начиная с Windows 7) можно использовать команду timeout, которая работает более корректно:


Сек = 5;
scr = Новый COMОбъект("WScript.Shell");
scr.Run("TIMEOUT -T " + Число(Сек) + " -NOBREAK", 0, 1);

Решение 2: Создание временного скрипта (VBScript/JScript)

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


Процедура Пауза_VBS(Мс)
    Сигнатура = Формат(ТекущаяДата(), "ДФ=yyyyMMddhhmmss");
    ПутьСкрипта = КаталогВременныхФайлов() + "sleep" + Сигнатура + ".vbs";
    
    ТекстСкрипта = Новый ТекстовыйДокумент;
    ТекстСкрипта.ДобавитьСтроку("WScript.Sleep(" + Формат(Мс, "ЧГ=0") + ")");
    ТекстСкрипта.Записать(ПутьСкрипта, КодировкаТекста.ANSI);
    
    WSHShell = Новый COMОбъект("WScript.Shell");
    WSHShell.Run("wscript.exe """ + ПутьСкрипта + """", 0, Истина);
    УдалитьФайлы(ПутьСкрипта);
КонецПроцедуры

Этот метод позволяет делать паузы любой длительности (например, 500 мс) и не создает видимых окон. Он считается одним из самых «профессиональных» способов без использования сторонних DLL.

Решение 3: Внешние компоненты (1С++ и другие)

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


Система = СоздатьОбъект("Система");
Система.Уснуть(5000); // Пауза в 5000 миллисекунд (5 секунд)

Этот метод вызывает системную функцию Sleep напрямую из Windows API через kernel32.dll. Также существуют легкие компоненты вроде vk_sleep.dll или TerminalSleep, которые делают ровно то же самое, не перегружая систему лишним функционалом.

Решение 4: Рефакторинг через ОбработкаОжидания

Рассмотрим ситуацию с точки зрения архитектуры приложения. Часто пауза нужна для того, чтобы не блокировать интерфейс при длительных операциях. В этом случае правильнее не «усыплять» поток, а разбить процедуру на этапы. В 1С 7.7 и 8.x есть встроенный механизм ОбработкаОжидания.

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

  1. Выполняем первую часть данных.
  2. Сохраняем текущее состояние (например, номер последней обработанной строки) в переменные модуля или реквизиты формы.
  3. Подключаем обработчик ожидания: ПодключитьОбработчикОжидания("ПродолжитьОбработку", 5, Истина);.
  4. Процедура ПродолжитьОбработку выполняет следующую порцию данных и, если нужно, снова подключает себя через паузу.

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

Решение 5: Использование SQL (для клиент-серверных баз)

Если код выполняется на сервере и у вас есть доступ к MS SQL Server, можно использовать специфическую команду WAITFOR DELAY. Выясним, как это работает через ADO:


Connection = Новый COMОбъект("ADODB.Connection");
// Настройка соединения с вашей БД...
Connection.Execute("WAITFOR DELAY '00:00:05'"); // Пауза на 5 секунд

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

Сравнительный анализ методов

Проанализируем все рассмотренные варианты, чтобы выбрать лучший:

Подводя итог, для быстрых правок в коде рекомендуем использовать ping или timeout через WScript.Shell. Если же ваша задача требует высокой стабильности и работы с миллисекундами — используйте внешние компоненты или создание временного скрипта WScript.Sleep. Главное — избегайте пустых циклов, берегите ресурсы процессора и комфорт ваших пользователей.

← На главную