Фоновые и регламентные задания 1С 8.3: запуск из кода, контроль и отладка

· 11 мин

Содержание

Фоновое задание в 1С 8.3 запускают серверным методом ФоновыеЗадания.Выполнить("ОбщийМодуль.Процедура", Параметры). Процедура должна быть экспортной и лежать в серверном общем модуле. Из тонкого и веб-клиента напрямую этот метод не вызвать: сначала уходите на сервер (&НаСервере в модуле формы), и уже там стартуете задание.

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

Как 1С выполняет фоновое задание: сеанс, сервер, контекст

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

Что важно знать до написания кода:

  • 🖥️ Выполняется только серверный код. Метод задания — экспортная процедура общего модуля с флажком «Сервер». Модули форм, модули объектов и клиентские модули не подходят.
  • 🚫 Никакого интерфейса. Вопрос(), ОткрытьФорму(), Предупреждение() в фоне не работают. Сообщения через Сообщить() или СообщениеПользователю не теряются — они копятся в задании, и их можно забрать.
  • 📦 Параметры — только сериализуемые. Массив, структура, ссылки, примитивы — да. Форма, ТабличныйДокумент из формы, объект с несохранёнными изменениями — лучше передавать ссылку или данные в структуре.
  • 🔁 Параллельность. Вызывающий код не ждёт завершения: Выполнить() возвращает объект ФоновоеЗадание сразу, а работа идёт параллельно.

Где физически исполняется код, зависит от варианта базы:

Вариант базыКто выполняет фоновое заданиеЧто учесть
Клиент-серверныйРабочий процесс кластера серверов 1СНагрузка ложится на сервер, клиенту всё равно, закрыт ли он
Файловый, тонкий/толстый клиентПроцесс клиентского приложения, открывшего базуЗакрыли программу — задание прервётся
Файловый, веб-клиентПроцесс веб-сервера с публикацией базыПерезапуск веб-сервера обрывает задание

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

Запуск фонового задания из кода: тонкий, толстый и веб-клиент

Базовый вызов

Сначала серверная процедура, которую будет выполнять задание. Создайте общий модуль, например ФоновыеОбработки, и отметьте в его свойствах «Сервер» (флажок «Вызов сервера» здесь не нужен).

// Общий модуль ФоновыеОбработки (Сервер)
Процедура ПересчитатьОстатки(ДатаНачала, АдресРезультата) Экспорт

    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК Всего
                   |ИЗ Справочник.Номенклатура КАК Н";
    Выборка = Запрос.Выполнить().Выбрать();
    Выборка.Следующий();

    Результат = Новый Структура("Всего, Дата", Выборка.Всего, ТекущаяДатаСеанса());
    ПоместитьВоВременноеХранилище(Результат, АдресРезультата);

КонецПроцедуры

Теперь запуск из формы. Клиентская команда уходит на сервер, сервер стартует задание и возвращает его идентификатор:

&НаКлиенте
Перем ИдентификаторЗадания;

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

&НаСервере
Функция ЗапуститьНаСервере()

    АдресРезультата = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор);

    Параметры = Новый Массив;
    Параметры.Добавить(НачалоМесяца(ТекущаяДатаСеанса()));
    Параметры.Добавить(АдресРезультата);

    Задание = ФоновыеЗадания.Выполнить(
        "ФоновыеОбработки.ПересчитатьОстатки",
        Параметры,
        "ПересчетОстатков",              // ключ: не даст запустить второй экземпляр
        "Пересчёт остатков из формы");   // наименование для списка заданий

    Возврат Задание.УникальныйИдентификатор;

КонецФункции

АдресРезультата объявите реквизитом формы типа «Строка», чтобы он пережил переход с сервера на клиент.

Четыре параметра ФоновыеЗадания.Выполнить():

  1. Имя метода — строка "ИмяМодуля.ИмяПроцедуры". Ошибка в имени выяснится только при запуске.
  2. Параметры — массив; порядок элементов совпадает с порядком параметров процедуры.
  3. Ключ — необязательный. Пока задание с этим ключом и этим методом активно, второе с тем же ключом не стартует, платформа выдаст исключение.
  4. Наименование — необязательное, но заполняйте его: так задание проще найти в списке и в журнале регистрации.

Толстый клиент

В обычном приложении (толстый клиент) менеджер ФоновыеЗадания доступен и в клиентском коде. Но пишите так же, как для тонкого клиента — через серверную процедуру. Тогда код не придётся переделывать при переходе на управляемые формы.

Типовые конфигурации на БСП

В БП 3.0, ЗУП 3.1, УТ 11 и других конфигурациях на Библиотеке стандартных подсистем используют готовый механизм длительных операций. На сервере — ДлительныеОперации.ВыполнитьВФоне() с параметрами из ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор). На клиенте — ДлительныеОперацииКлиент.ОжидатьЗавершение() с описанием оповещения.

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

Регламентные задания 1С: расписание и ручной запуск

Регламентное задание — это фоновое задание, которое платформа стартует сама по расписанию. Его метод задаётся в метаданных, а не в коде.

Создание в конфигураторе

  1. В дереве метаданных откройте ветку Общие → Регламентные задания и добавьте новый объект.
  2. В поле «Имя метода» выберите экспортную процедуру серверного общего модуля.
  3. Включите флажок «Предопределенное», если задание должно существовать в базе всегда в одном экземпляре.
  4. Флажок «Использование» включает задание. Без него расписание игнорируется.
  5. Задайте расписание: дни, время начала и окончания, период повтора.
  6. Укажите число повторных попыток при аварийном завершении и интервал между ними — для обменов это спасает от разовых сетевых сбоев.

Для предопределённого задания процедура может быть без параметров. Если в процедуре есть параметры, значения задаются у самого задания в базе.

Включение и расписание в пользовательском режиме

В типовых конфигурациях на БСП список заданий открывается через Администрирование → Обслуживание → Регламентные операции → Регламентные и фоновые задания. Здесь видно последний запуск, его результат и следующее время старта. Двойной щелчок открывает карточку: включить, сменить расписание, указать пользователя, от имени которого задание выполняется.

Для заданий, которые создают или изменяют документы, указывайте пользователя явно. Тогда в журнале регистрации видно, от чьего имени прошли изменения, а права задания совпадают с правами этого пользователя.

Запустить регламентное задание вне расписания

У объекта регламентного задания нет метода «выполнить сейчас». В списке на БСП есть одноимённая команда «Выполнить сейчас» — она стартует фоновое задание с тем же методом и параметрами. Из кода делается то же самое:

&НаСервере
Процедура ВыполнитьОбменСейчас()

    МетаданныеЗадания = Метаданные.РегламентныеЗадания.ОбменДанными;
    ФоновыеЗадания.Выполнить(МетаданныеЗадания.ИмяМетода, , ,
        "Ручной запуск: " + МетаданныеЗадания.Синоним);

КонецПроцедуры

Файловая база: кто запускает регламентные задания

В файловом варианте отдельного сервера нет. Регламентные задания выполняет одно из открытых клиентских приложений — платформа выбирает его сама. Нет открытых сеансов — задания не выполняются.

Управлять этим можно параметром командной строки /AllowExecuteScheduledJobs:

  • -Off — этот экземпляр клиента никогда не выполняет регламентные задания;
  • -Force — выполняет их принудительно.

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

Результат фонового задания и оповещение пользователя

Задание работает отдельно от формы, поэтому результат забирают тремя способами.

Что нужно получитьЧемГде
Данные (таблица, структура, файл)ПоместитьВоВременноеХранилище() в задании → ПолучитьИзВременногоХранилища() в формеСервер
Тексты сообщенийЗадание.ПолучитьСообщенияПользователю(Истина)Сервер
Состояние и текст ошибкиЗадание.Состояние, Задание.ИнформацияОбОшибкеСервер

Проверка состояния по обработчику ожидания:

&НаКлиенте
Процедура ПроверитьЗадание()

    Состояние = СостояниеЗаданияНаСервере(ИдентификаторЗадания);

    Если Состояние = "Активно" Тогда
        ПодключитьОбработчикОжидания("ПроверитьЗадание", 2, Истина);
    ИначеЕсли Состояние = "Завершено" Тогда
        ПоказатьОповещениеПользователя("Пересчёт завершён");
        ЗагрузитьРезультат();
    Иначе
        ПоказатьПредупреждение(, "Задание не выполнено: " + Состояние);
    КонецЕсли;

КонецПроцедуры

&НаСервереБезКонтекста
Функция СостояниеЗаданияНаСервере(Идентификатор)

    Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(Идентификатор);
    Если Задание = Неопределено Тогда
        Возврат "Не найдено";
    КонецЕсли;

    Если Задание.Состояние = СостояниеФоновогоЗадания.Активно Тогда
        Возврат "Активно";
    ИначеЕсли Задание.Состояние = СостояниеФоновогоЗадания.Завершено Тогда
        Возврат "Завершено";
    ИначеЕсли Задание.Состояние = СостояниеФоновогоЗадания.ЗавершеноАварийно Тогда
        Возврат ПодробноеПредставлениеОшибки(Задание.ИнформацияОбОшибке);
    КонецЕсли;

    Возврат "Отменено";

КонецФункции

ЗагрузитьРезультат() — ваша серверная процедура, которая читает ПолучитьИзВременногоХранилища(АдресРезультата) и выводит данные на форму.

Несколько практических правил:

  • ⏱️ Интервал проверки — 1–5 секунд. Опрос каждые 0,1 секунды создаёт лишние серверные вызовы, особенно когда форму открыли 50 пользователей.
  • 🧹 Хранилище привязывайте к форме. Адрес, полученный с УникальныйИдентификатор формы, очищается при её закрытии. Без этого данные висят до конца сеанса.
  • ✋ Дайте кнопку отмены. Задание.Отменить() на сервере ставит задание в состояние «Отменено». Код в задании не прерывается посреди записи — отмена срабатывает между операциями, поэтому длинный цикл не остановится мгновенно.
  • 📣 Оповещайте после закрытия формы. Если пользователь закрыл форму, обработчик ожидания исчезнет вместе с ней. Для долгих заданий пишите итог в журнал регистрации или в регистр, а пользователю показывайте его при следующем открытии.

Отладка фонового задания

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

Порядок для конфигуратора:

  1. Запустите отладку как обычно (F5).
  2. В Конфигураторе откройте Отладка → Подключение и включите автоматическое подключение для фоновых заданий.
  3. Поставьте точку останова в процедуре общего модуля и запустите задание.

Для клиент-серверной базы сервер 1С должен работать в режиме отладки (служба запускается с ключом -debug). На рабочем сервере этот режим не держат постоянно: он замедляет работу.

Быстрый путь без отладчика: временно вызовите процедуру задания напрямую в серверной процедуре формы вместо ФоновыеЗадания.Выполнить(). Ошибка всплывёт сразу, с номером строки. В БСП для этого есть параметр выполнения, который запускает длительную операцию в текущем сеансе, а не в фоне.

Почему фоновое или регламентное задание не запускается

Большинство сбоев видно в журнале регистрации: Администрирование → Обслуживание → Журнал регистрации, отбор по приложению «Фоновое задание» и по уровню «Ошибка».

Диагностика: выберите симптом

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

Нагрузка на сервер: как не перегрузить базу фоновыми заданиями

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

Расписание

  • 📅 Разносите тяжёлые задания по времени. Обмен, пересчёт итогов, полнотекстовый индекс и загрузка банковских выписок в одну и ту же минуту дают пик блокировок.
  • ⏳ Не ставьте период повтора меньше времени выполнения. Если обмен идёт 4 минуты, повтор каждые 60 секунд не ускорит его: следующий запуск просто не стартует, пока активен предыдущий, или упрётся в блокировки.
  • 🌙 Тяжёлое — ночью. Обновление индекса полнотекстового поиска и пересчёт агрегатов в рабочие часы замедляют проведение документов.

Код задания

  • 🧩 Порции вместо одной транзакции. Обработка 100 000 документов одной транзакцией держит блокировки весь час работы. Порции по 500–1000 объектов со своей транзакцией каждая освобождают таблицы между порциями.
  • 🔀 Параллельные потоки — осторожно. Разбить данные на 4 части и запустить 4 фоновых задания реально ускоряет обработку на сервере с несколькими ядрами. Но части не должны пересекаться по данным, иначе потоки будут ждать друг друга на управляемых блокировках. В свежих версиях БСП для этого есть готовые функции многопоточного выполнения в модуле ДлительныеОперации.
  • 📉 Не ждите задание синхронно. ОжидатьЗавершенияВыполнения() на сервере блокирует серверный вызов формы. Если ждать всё равно приходится, задавайте таймаут в секундах.

Контроль

В консоли администрирования серверов в списке сеансов фоновые задания видны с типом приложения «Фоновое задание». Длинный список таких сеансов при обычной нагрузке — признак, что задания не успевают завершиться до следующего запуска.

Код для быстрой проверки, что сейчас выполняется в базе:

&НаСервереБезКонтекста
Функция АктивныеЗадания()

    Отбор = Новый Структура("Состояние", СостояниеФоновогоЗадания.Активно);
    Результат = Новый Массив;
    Для Каждого Задание Из ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор) Цикл
        Результат.Добавить(Задание.Наименование + " — с " + Формат(Задание.Начало, "ДФ=HH:mm:ss"));
    КонецЦикла;
    Возврат Результат;

КонецФункции

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

Можно ли запустить фоновое задание из модуля объекта или обработки?
Только косвенно. Метод задания обязан находиться в серверном общем модуле. Из модуля объекта вызовите ФоновыеЗадания.Выполнить() с именем процедуры общего модуля, а нужный объект передайте ссылкой в параметрах.
Как запустить внешнюю обработку в фоне?
Фоновое задание не может вызвать метод самой внешней обработки по имени. Обходят так: в общем модуле пишут процедуру, которая подключает обработку по адресу во временном хранилище или из справочника дополнительных обработок и вызывает её экспортный метод. В БСП это делает подсистема дополнительных отчётов и обработок.
Сколько фоновых заданий можно запускать одновременно?
Жёсткого лимита на уровне языка нет, ограничивают ресурсы сервера. Каждое задание — отдельный сеанс с памятью и соединением с СУБД. На сервере с 4 ядрами 3–4 параллельных тяжёлых задания обычно дают выигрыш, 20 — уже очередь на блокировках.
Нужна ли отдельная лицензия для фонового задания?
Нет. Фоновые задания и регламентные задания не занимают клиентскую лицензию, их сеансы лицензируются в составе сервера.
Можно ли запустить фоновое задание из другого фонового задания?
Да, вложенный запуск через ФоновыеЗадания.Выполнить() работает. Так устроены многопоточные обработки: управляющее задание делит данные на порции и стартует несколько дочерних, а затем собирает их результаты.