Ресурсоёмкие операции — формирование отчётов по сложным компоновкам, пакетное перепроведение документов, синхронизация с внешними API — блокируют интерфейс и снижают производительность работы пользователей. Платформа «1С:Предприятие» предоставляет механизм фоновых заданий, исполняющих код в отдельных сеансах кластера. Грамотное использование этого механизма разгружает интерактивные сеансы, изолирует сбои и повышает стабильность решения. В материале рассматриваются устройство фоновых процессов, детали запуска из внешних обработок, приёмы мониторинга зависших заданий и типичные ошибки с примерами кода, ориентированными на опытного разработчика.
- Что такое фоновые задания?
- Примеры использования фоновых заданий в 1С
- Программный код, как создать и запустить фоновое задание в 1С
- Работа с результатом фонового задания
- Регламентные задания: фоновое выполнение по расписанию
- Мониторинг и управление фоновыми процессами
- Типичные ошибки при работе с фоновыми заданиями и рекомендации
- Расширенные примеры при работе с фоновыми заданиями в 1С
Что такое фоновые задания?
Фоновое задание — это отдельный сеанс кластера, запускаемый либо явным программным вызовом, либо по расписанию. Сеанс полностью изолирован: отсутствует доступ к формам и модальным методам, состояние клиента не передаётся. Все данные, которые необходимо обработать в фоне, сериализуются платформой и передаются через параметры; поддерживаются примитивные типы, ссылки, структуры, массивы, двоичные данные, но не таблицы значений, деревья или COM-объекты — для них используется временное хранилище.
Жизненный цикл: постановка в очередь, выполнение рабочим процессом, завершение с одним из статусов: «Выполняется», «Выполнено», «Ошибка», «Отменено». Задание идентифицируется уникальным ключом, что предотвращает дублирование при повторных попытках запуска с тем же ключом. Регламентные задания технически используют тот же механизм, но инициируются расписанием. Управление очередью и лимитами — на уровне параметров кластера.
Примеры использования фоновых заданий в 1С
- Массовая обработка документов: перепроведение 100 000 записей или расчёт себестоимости партий. Фоновый процесс может вернуть протокол с количеством успешных операций и списком ошибок.
- Загрузка данных из внешних файлов: CSV, Excel, XML. Передаётся адрес временного хранилища с двоичными данными, внутри задания выполняется парсинг и импорт.
- Рассылки уведомлений: перебор тысяч получателей email или SMS не должен заставлять пользователя ждать.
- Интеграция по HTTP/веб-сервисам: запросы с потенциально длительным откликом; в фоне можно реализовать повторные попытки и корректную обработку тайм-аутов.
- Формирование отчётов с постобработкой: генерация табличного документа и его сохранение во временное хранилище для последующей выдачи пользователю.
- Изоляция ошибок — дополнительное преимущество: исключение в фоновом задании не затрагивает основной сеанс, а фиксируется в журнале регистрации.
Программный код, как создать и запустить фоновое задание в 1С
Базовый способ — глобальный метод ВыполнитьФоновоеЗадание. Обязательные аргументы: полное имя экспортной процедуры общего модуля, ключ, имя сервера (можно пустую строку), имя выполняемой функции и параметры. Метод возвращает объект ФоновоеЗадание или Неопределено при невозможности постановки в очередь.
Пример 1: запуск с передачей таблицы через временное хранилище
// Серверный или клиентский код
Ключ = Строка(Новый УникальныйИдентификатор);
ТаблицаДляОбработки = ПолучитьДанныеИзФормы();
АдресВХ = ПоместитьВоВременноеХранилище(ТаблицаДляОбработки, Ключ);
Параметры = Новый Структура;
Параметры.Вставить("АдресДанных", АдресВХ);
Параметры.Вставить("ИдентификаторОперации", Ключ);
Задание = ВыполнитьФоновоеЗадание(
"ОбщийМодульДлительныхОпераций.ОбработатьДанные",
Ключ,
"",
"ОбработатьДанные",
Параметры
);
Если Задание = Неопределено Тогда
УдалитьИзВременногоХранилища(АдресВХ);
ВызватьИсключение "Очередь фоновых заданий переполнена";
КонецЕсли;
Процедура-обработчик в общем модуле:
Процедура ОбработатьДанные(Параметры) Экспорт Адрес = Параметры.АдресДанных; Данные = ПолучитьИзВременногоХранилища(Адрес); Если Данные = Неопределено Тогда ЗаписатьОшибку(Параметры.ИдентификаторОперации, "Данные не найдены"); Возврат; КонецЕсли; // длительная обработка Результат = ВыполнитьРасчёт(Данные); АдресРезультата = ПоместитьВоВременноеХранилище(Результат); СохранитьРезультатВРегистре(Параметры.ИдентификаторОперации, АдресРезультата); КонецПроцедуры
Пример 2: запуск кода из внешней обработки
Фоновое задание умеет вызывать только экспортные процедуры общих модулей конфигурации. Для выполнения метода, определённого во внешней обработке, применяют модуль-посредник, который загружает обработку из временного хранилища или по известному пути и вызывает нужный метод.
Помещение внешней обработки в хранилище и запуск:
// Загрузка обработки в двоичные данные и помещение во временное хранилище
ДанныеОбработки = Новый ДвоичныеДанные(ПутьКВнешнейОбработке);
АдресОбработки = ПоместитьВоВременноеХранилище(ДанныеОбработки, УникальныйИдентификатор);
Параметры = Новый Структура;
Параметры.Вставить("АдресОбработки", АдресОбработки);
Параметры.Вставить("ПараметрыОбработки", ДополнительныеПараметры);
Задание = ВыполнитьФоновоеЗадание(
"ОбщийМодульСерверныхВызовов.ВыполнитьВнешнююОбработку",
Ключ,
"",
"ВыполнитьВнешнююОбработку",
Параметры
);
Общий модуль ОбщийМодульСерверныхВызовов:
Процедура ВыполнитьВнешнююОбработку(ПараметрыЗапуска) Экспорт
Адрес = ПараметрыЗапуска.АдресОбработки;
ДвоичныеДанныеОбработки = ПолучитьИзВременногоХранилища(Адрес);
Если ДвоичныеДанныеОбработки = Неопределено Тогда
ЗаписатьОшибку("Внешняя обработка не найдена в хранилище");
Возврат;
КонецЕсли;
Обработка = ВнешниеОбработки.Создать(ДвоичныеДанныеОбработки, Ложь);
// Предполагается, что в модуле объекта есть экспортный метод Выполнить
Обработка.Выполнить(ПараметрыЗапуска.ПараметрыОбработки);
КонецПроцедуры
Этот подход позволяет централизованно управлять исполнением внешних обработок в фоне.
Работа с результатом фонового задания
Асинхронное выполнение требует организации опроса состояния. Рассматриваются три основных шаблона.
Пример 3: активный опрос в цикле с задержкой
// Серверный контекст Задание = ЗапуститьФоновоеЗадание(...); Пока Истина Цикл Состояние = Задание.ПолучитьСостояние(); Если Состояние.Статус = "Выполнено" Тогда Результат = ПолучитьРезультатИзХранилища(Ключ); Прервать; ИначеЕсли Состояние.Статус = "Ошибка" Тогда ВызватьИсключение Состояние.КраткоеПредставлениеОшибки; КонецЕсли; // Пауза 2 секунды Пауза(2000); КонецЦикла;
Для клиента метод Пауза недоступен, поэтому в управляемой форме используется таймер.
Пример 4: клиентский таймер в форме
&НаКлиенте
Перем ТаймерПроверки, ФоновоеЗадание, КлючЗадания;
&НаКлиенте
Процедура ЗапуститьОбработку()
ФоновоеЗадание = СерверныйЗапуск(...);
КлючЗадания = ФоновоеЗадание.Ключ;
ТаймерПроверки = Новый Таймер("ПроверкаЗадания", 2000, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ПроверкаЗадания(Таймер)
Состояние = ФоновоеЗадание.ПолучитьСостояние();
Если Состояние.Статус = "Выполнено" Тогда
Таймер.Остановить();
Результат = ПолучитьРезультатСервер(КлючЗадания);
ОтобразитьРезультат(Результат);
ИначеЕсли Состояние.Статус = "Ошибка" Тогда
Таймер.Остановить();
ПоказатьПредупреждение(Состояние.КраткоеПредставлениеОшибки);
КонецЕсли;
КонецПроцедуры
Остановка задания:
// Инициируется пользователем из интерфейса Если ФоновоеЗадание <> Неопределено И ФоновоеЗадание.ПолучитьСостояние().Статус = "Выполняется" Тогда ОтменитьФоновоеЗадание(ФоновоеЗадание); КонецЕсли;
Регламентные задания: фоновое выполнение по расписанию
Регламентное задание — объект метаданных, выполняющий заданную процедуру по расписанию. Расписание конфигурируется программно.
Пример 5: программное управление регламентным заданием
Задание = РегламентныеЗадания.ОбновлениеИндексов; Если Не Задание.Использование Тогда Задание.Использование = Истина; КонецЕсли; Расписание = Новый РасписаниеРегламентногоЗадания; Расписание.ПериодПовтораДня = 1; Расписание.ВремяНачала = Дата(1,1,1,3,0,0); // 03:00 Задание.Расписание = Расписание; // Принудительный запуск сейчас Задание.Выполнить();
Проверить состояние последнего выполнения можно через свойство ПоследнееЗадание, возвращающее объект ФоновоеЗадание с полным набором статусов.
Мониторинг и управление фоновыми процессами
Штатная консоль фоновых заданий показывает очередь и статусы. Для автоматического поиска зависших заданий удобно использовать программный интерфейс.
Пример 6: обнаружение и отмена долго выполняющихся заданий
// Выполняется, например, в регламентном задании каждые 10 минут ВсеЗадания = ПолучитьФоновыеЗадания(); ТекущееВремя = ТекущаяДатаСеанса(); МаксимальнаяДлительностьСек = 600; // 10 минут Для Каждого Задание Из ВсеЗадания Цикл Если Задание.Статус = "Выполняется" Тогда ВремяВыполнения = ТекущееВремя - Задание.ДатаНачала; Если ВремяВыполнения > МаксимальнаяДлительностьСек Тогда // Задание считается зависшим Попытка ОтменитьФоновоеЗадание(Задание); ЗаписьЖурналаРегистрации( "ФоновоеЗадание.Контроль", УровеньЖурналаРегистрации.Предупреждение, , , "Отменено зависшее задание с ключом %1, выполнявшееся %2 сек", Задание.Ключ, ВремяВыполнения ); Исключение ЗаписьЖурналаРегистрации( "ФоновоеЗадание.Контроль", УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()) ); КонецПопытки; КонецЕсли; КонецЕсли; КонецЦикла;
Такой мониторинг можно оформить отдельным регламентным заданием, очищающим очередь от «зависших» процессов.
Типичные ошибки при работе с фоновыми заданиями и рекомендации
- Несериализуемые параметры. Прямая передача таблиц или COM-объектов вызывает исключение «Не удалось сериализовать параметр». Используйте временное хранилище, как показано в Примере 1.
- Дублирование заданий из-за отсутствия ключа или повторного использования одного ключа без учёта уже активного задания. Проверяйте наличие задания с таким ключом через
ПолучитьФоновыеЗадания. - Потеря данных во временном хранилище. Если задание не запустилось, а адрес не удалён, данные остаются до истечения времени жизни (по умолчанию 20 минут). В Примере 1 показано корректное удаление при ошибке.
- Зависание основного сеанса на вызове
ОжидатьЗавершениеФоновогоЗаданиябез таймаута. Всегда задавайте ограничение. - Игнорирование исключений внутри фонового метода. Необработанная ошибка переводит задание в статус «Ошибка», но детали теряются. Всегда применяйте Попытка…Исключение и сохраняйте информацию.
- Массовый параллельный запуск порождает блокировки в базе данных. Ограничивайте число одновременно выполняемых заданий через настройки кластера или собственные семафоры (например, на основе регистра сведений).
- Запуск внешних обработок напрямую. Платформа не позволяет указать метод модуля внешней обработки в
ВыполнитьФоновоеЗадание. Используйте общий модуль-адаптер, как в Примере 2.
Расширенные примеры при работе с фоновыми заданиями в 1С
Этот раздел для специфических задач, которые, однако, могут возникнуть при разработке фоновых операций.
Ожидание завершения с таймаутом и немедленная реакция
Классический вызов ОжидатьЗавершениеФоновогоЗадания удобен, но блокирует текущий поток. Если нужно сохранить управление в цикле, применяют следующий шаблон:
Функция ДождатьсяЗадания(Задание, МаксимальноеВремяОжиданияСек = 300) Экспорт ВремяНачала = ТекущаяДатаСеанса(); Пока Истина Цикл Если Задание.ОжидатьЗавершениеФоновогоЗадания(2) Тогда // ждем 2 секунды Состояние = Задание.ПолучитьСостояние(); Возврат Состояние.Статус = "Выполнено"; КонецЕсли; Если ТекущаяДатаСеанса() - ВремяНачала > МаксимальноеВремяОжиданияСек Тогда Возврат Ложь; // превышен общий таймаут КонецЕсли; // здесь можно обновить прогресс в интерфейсе КонецЦикла; КонецФункции
Этот метод не «вешает» серверный вызов на длительное время и позволяет периодически выполнять полезные действия — например, записывать промежуточный статус в регистр.
Семафор для ограничения числа одновременно выполняющихся фоновых заданий
Массовый запуск сотен заданий может перегрузить сервер БД блокировками. Вместо расчёта на настройки кластера иногда надёжнее реализовать собственный семафор через константу или регистр сведений.
Идея: перед запуском проверять счетчик активных заданий, при превышении лимита откладывать запуск или ставить в пользовательскую очередь.
Пример с использованием регистра сведений «СемафорФоновыхЗаданий» (измерения: КлючЗадания, ресурс: ДатаНачала):
МаксимумОдновременных = 5;
// Функция проверки, можно ли запустить новое задание
Функция МожноЗапуститьЕщеОдно() Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ КОЛИЧЕСТВО(Р) КАК Кол
ИЗ РегистрСведений.СемафорФоновыхЗаданий КАК Р
ГДЕ Р.ДатаНачала ЕСТЬ NULL";
Результат = Запрос.Выполнить().Выбрать();
Результат.Следующий();
Возврат Результат.Кол < МаксимумОдновременных;
КонецФункции
// Перед запуском:
Если Не МожноЗапуститьЕщеОдно() Тогда
// Поставить в отложенную очередь (например, запись в отдельный регистр)
Возврат;
КонецЕсли;
// Резервируем слот
Ключ = Новый УникальныйИдентификатор;
Набор = РегистрыСведений.СемафорФоновыхЗаданий.СоздатьНаборЗаписей();
Запись = Набор.Добавить();
Запись.КлючЗадания = Ключ;
Запись.ДатаНачала = Неопределено; // признак "активно"
Набор.Записать();
// Запускаем задание, передавая ключ слота
Параметры = Новый Структура("КлючСлота", Ключ);
Задание = ВыполнитьФоновоеЗадание("...", Ключ, "", "...", Параметры);
Если Задание = Неопределено Тогда
// Удаляем запись семафора
УдалитьСлот(Ключ);
КонецЕсли;
// Внутри фонового задания после завершения (в блоке Попытка-Исключение):
Попытка
// полезная работа
Исключение
// обработка ошибки
КонецПопытки;
// Освобождаем слот
Набор = РегистрыСведений.СемафорФоновыхЗаданий.СоздатьНаборЗаписей();
Запись = Набор.Добавить();
Запись.КлючЗадания = Параметры.КлючСлота;
Запись.ДатаНачала = ТекущаяДатаСеанса(); // теперь дата заполнена, значит слот свободен
Набор.Записать();
Такой подход дает полный контроль над параллелизмом независимо от настроек кластера.
Автоматический перезапуск при ошибке с нарастающей задержкой
В интеграционных задачах (обращение к внешнему API) упавшее по таймауту фоновое задание имеет смысл перезапустить через некоторое время. Для этого внутри задания после отлова ошибки проверяют счётчик попыток и при необходимости планируют повтор.
Процедура ВызовВнешнегоСервиса(Параметры) Экспорт Попытка Ответ = ВыполнитьHTTPЗапрос(Параметры.URL); ОбработатьОтвет(Ответ); Исключение НомерПопытки = Параметры.НомерПопытки; Если НомерПопытки >= 3 Тогда ЗаписатьФинальнуюОшибку(Параметры.Идентификатор, ОписаниеОшибки()); Иначе // Планируем перезапуск через регламентное задание-диспетчер // или просто запускаем с задержкой, но в фоне нельзя сделать Паузу для самого себя, // поэтому используем другое регламентное задание, которое подхватит отложенную задачу. ЗапланироватьПовторнуюПопытку(Параметры.Идентификатор, НомерПопытки + 1); КонецЕсли; КонецПопытки; КонецПроцедуры
Сам диспетчер отложенных задач — это регламентное задание, раз в минуту проверяющее таблицу отложенных вызовов и запускающее фоновые задания для тех, у кого подошло время.
Процедура ДиспетчерОтложенныхЗаданий() Экспорт
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ... ИЗ РегистрСведений.ОтложенныеЗадания ГДЕ ВремяЗапуска <= &ТекущееВремя";
Запрос.УстановитьПараметр("ТекущееВремя", ТекущаяДатаСеанса());
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// запускаем фоновое задание на основе данных выборки
Параметры = Выборка.Параметры;
Параметры.НомерПопытки = Выборка.НомерПопытки;
ВыполнитьФоновоеЗадание("...", Выборка.Ключ, "", "...", Параметры);
// удаляем запись об отложенном запуске
УдалитьОтложенноеЗадание(Выборка.Ключ);
КонецЦикла;
КонецПроцедуры
Такая конструкция обеспечивает надёжную обработку нестабильных внешних сервисов.
Передача и возврат нескольких разнотипных наборов данных через временное хранилище
Часто требуется передать не одну таблицу, а несколько (например, таблица товаров и таблица контрагентов), и аналогично получить обратно несколько результатов.
// Формирование параметров
ТаблицаТоваров = ...;
ТаблицаКонтрагентов = ...;
АдресТоваров = ПоместитьВоВременноеХранилище(ТаблицаТоваров, Ключ);
АдресКонтрагентов = ПоместитьВоВременноеХранилище(ТаблицаКонтрагентов, Ключ);
Параметры = Новый Структура;
Параметры.Вставить("АдресТоваров", АдресТоваров);
Параметры.Вставить("АдресКонтрагентов", АдресКонтрагентов);
Параметры.Вставить("ИдентификаторСеанса", Ключ);
// Внутри фонового метода:
Процедура ОбработкаДанных(Параметры) Экспорт
Товары = ПолучитьИзВременногоХранилища(Параметры.АдресТоваров);
Контрагенты = ПолучитьИзВременногоХранилища(Параметры.АдресКонтрагентов);
РезультатТовары = ОбработатьТовары(Товары);
РезультатКонтрагенты = ОбработатьКонтрагенты(Контрагенты);
АдресРезТов = ПоместитьВоВременноеХранилище(РезультатТовары);
АдресРезКонт = ПоместитьВоВременноеХранилище(РезультатКонтрагенты);
Результат = Новый Структура("АдресТовары, АдресКонтрагенты", АдресРезТов, АдресРезКонт);
АдресРезультата = ПоместитьВоВременноеХранилище(Результат);
СохранитьАдресРезультата(Параметры.ИдентификаторСеанса, АдресРезультата);
КонецПроцедуры
При получении результата из основного сеанса:
АдресРезультата = ПолучитьАдресРезультата(Ключ); РезультатСтруктура = ПолучитьИзВременногоХранилища(АдресРезультата); ТоварыОбработанные = ПолучитьИзВременногоХранилища(РезультатСтруктура.АдресТовары); КонтрагентыОбработанные = ПолучитьИзВременногоХранилища(РезультатСтруктура.АдресКонтрагенты); // не забыть удалить адреса
Это экономит время и делает код прозрачным.
Запуск фонового задания на конкретном рабочем сервере
Когда кластер состоит из нескольких серверов с разной аппаратной конфигурацией, ресурсоёмкие задания имеет смысл направлять на выделенный узел.
ИмяЦелевого = "ProductionServer2"; Задание = ВыполнитьФоновоеЗадание( "ОбщийМодульТяжелыхРасчетов.ВыполнитьРасчет", Ключ, ИмяЦелевого, // имя рабочего сервера, как оно указано в консоли кластера "ВыполнитьРасчет", Параметры );
Если сервер недоступен или перегружен, вызов вернёт Неопределено. В этом случае можно либо попробовать другой сервер, либо запустить без указания имени.
Фиксация ошибок фонового задания в журнале регистрации с контекстом
Чтобы потом не гадать, на каких данных упало задание, нужно записывать в журнал не только текст ошибки, но и значимые параметры.
Процедура ОтветственнаяОперация(Параметры) Экспорт
Попытка
// код
Исключение
СообщениеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
Контекст = СтрШаблон("Ключ: %1, Период: %2, Организация: %3",
Параметры.Ключ, Параметры.Период, Параметры.Организация);
ЗаписьЖурналаРегистрации(
"ФоновоеЗадание.Ошибка",
УровеньЖурналаРегистрации.Ошибка,
,
Параметры.ИмяМетода,
СтрШаблон("%1; Контекст: %2", СообщениеОшибки, Контекст)
);
// дополнительно сохраняем в регистр для интерактивного просмотра
СохранитьОшибкуВРегистре(Параметры.Ключ, СообщениеОшибки, Контекст);
КонецПопытки;
КонецПроцедуры
Журнал регистрации затем можно анализировать стандартными отчётами или консолью.
Заключение
Фоновые и регламентные задания — это мощный инструмент для построения производительных и отказоустойчивых прикладных решений. Приведённые примеры демонстрируют запуск, контроль состояния, отмену и мониторинг зависших процессов в реальных сценариях. Владение этими приёмами позволяет разработчику эффективно распределять нагрузку, избавлять интерфейс от длительных пауз и автоматизировать критические серверные операции.

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