Фоновое задание во внешней обработке 1С на конфигурации с БСП запускается через подсистему «Длительные операции»: форма вызывает ДлительныеОперации.ВыполнитьВФоне, передавая ей метод-обёртку ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки, ссылку на зарегистрированную дополнительную обработку и имя экспортной процедуры её модуля. Процедура работает в фоновом сеансе, сообщает прогресс через ДлительныеОперации.СообщитьПрогресс и кладёт результат во временное хранилище, а клиент ждёт завершения через ДлительныеОперацииКлиент.ОжидатьЗавершение.

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

Почему для внешней обработки нужна обёртка БСП

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

  1. Внешняя обработка зарегистрирована в справочнике ДополнительныеОтчетыИОбработки — там хранятся её двоичные данные.
  2. В фоне выполняется общий метод ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки.
  3. Он по ссылке подключает обработку в фоновом сеансе, создаёт её объект и вызывает нужную экспортную процедуру.
Фоновое задание во внешней обработке: форма передаёт задачу фоновому сеансу и получает прогресс
Фоновое задание во внешней обработке: форма передаёт задачу фоновому сеансу и получает прогресс

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

Шаг 1. Регистрационные сведения обработки

В модуле объекта описываем обработку для подсистемы «Дополнительные отчёты и обработки». Удобнее использовать функции БСП, чем собирать структуру вручную:

1С
Функция СведенияОВнешнейОбработке() Экспорт

	// Версия БСП, под которую написана обработка
	Сведения = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("3.1.5.1");
	Сведения.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
	Сведения.Версия = "1.0";
	Сведения.БезопасныйРежим = Ложь;
	Сведения.Информация = НСтр("ru = 'Пересчёт данных в фоновом режиме с индикацией'");

	Команда = Сведения.Команды.Добавить();
	Команда.Представление = НСтр("ru = 'Пересчёт данных'");
	Команда.Идентификатор = "ОткрытьФорму";
	Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();

	Возврат Сведения;

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

БезопасныйРежим = Ложь нужен, если обработка пишет данные или обращается к файлам и сети. Включение небезопасного режима администратор подтверждает при регистрации — это осознанное решение, а не формальность.

Шаг 2. Процедура, которая работает в фоне

Экспортная процедура модуля объекта принимает два параметра: структуру входных данных и адрес временного хранилища для результата.

1С
// Выполняется в фоновом задании.
//
// Параметры:
//  ПараметрыВыполнения - Структура - входные данные, переданные с формы
//  АдресРезультата - Строка - адрес временного хранилища для результата
//
Процедура ПересчитатьДанные(ПараметрыВыполнения, АдресРезультата) Экспорт

	ВсегоЭлементов = ПараметрыВыполнения.КоличествоЭлементов;
	Обработано = Новый Массив;
	ПоследнийПроцент = -1;

	Для НомерЭлемента = 1 По ВсегоЭлементов Цикл

		// Здесь — полезная работа над очередным элементом
		Если НомерЭлемента % 100 = 0 Тогда
			Обработано.Добавить(НомерЭлемента);
		КонецЕсли;

		Процент = Цел(100 * НомерЭлемента / ВсегоЭлементов);
		Если Процент <> ПоследнийПроцент Тогда
			ДлительныеОперации.СообщитьПрогресс(Процент,
				СтрШаблон(НСтр("ru = 'Обработано %1 из %2'"), НомерЭлемента, ВсегоЭлементов));
			ПоследнийПроцент = Процент;
		КонецЕсли;

	КонецЦикла;

	ПоместитьВоВременноеХранилище(Обработано, АдресРезультата);

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

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

Шаг 3. Запуск задания с сервера формы

Ссылку на элемент справочника дополнительных обработок лучше не искать по наименованию: его могут переименовать. При открытии формы из списка дополнительных обработок БСП передаёт ссылку на элемент справочника в параметрах формы — объявите у формы параметр ДополнительнаяОбработкаСсылка и сохраните значение в реквизит формы. Точное имя параметра сверьте с документацией вашей версии БСП.

1С
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

	ОбработкаСсылка = Параметры.ДополнительнаяОбработкаСсылка;

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

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

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

	ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
	ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = 'Пересчёт данных (доп. обработка)'");
	ПараметрыВыполнения.ЗапуститьВФоне = Истина;

	Возврат ДлительныеОперации.ВыполнитьВФоне(
		"ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки",
		ПараметрыЗадания, ПараметрыВыполнения);

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

ЗапуститьВФоне = Истина гарантирует запуск именно в фоне. Без этого флага в файловом варианте или в режиме отладки БСП может выполнить процедуру синхронно — для отладки удобно, для пользователей нет.

УникальныйИдентификатор формы передаётся, чтобы временное хранилище с результатом жило, пока открыта форма.

Шаг 4. Ожидание и прогресс на форме

На форме обработки — реквизиты Индикатор (число, элемент — поле индикатора) и СтрокаСостояния (строка). Стандартное окно ожидания отключаем, прогресс получаем через собственный обработчик.

1С
&НаКлиенте
Процедура Запустить(Команда)

	Индикатор = 0;
	СтрокаСостояния = "";

	ПараметрыЗапуска = Новый Структура("КоличествоЭлементов", КоличествоЭлементов);
	ДлительнаяОперация = ЗапуститьФоновоеЗадание(ПараметрыЗапуска);

	ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
	ПараметрыОжидания.ВыводитьОкноОжидания = Ложь;
	ПараметрыОжидания.ВыводитьПрогрессВыполнения = Истина;
	ПараметрыОжидания.ОповещениеОПрогрессеВыполнения =
		Новый ОписаниеОповещения("ПриПолученииПрогресса", ЭтотОбъект);
	ПараметрыОжидания.Интервал = 2;

	ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация,
		Новый ОписаниеОповещения("ПриЗавершенииЗадания", ЭтотОбъект), ПараметрыОжидания);

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

&НаКлиенте
Процедура ПриПолученииПрогресса(Состояние, ДополнительныеПараметры) Экспорт

	Если Состояние.Статус = "Выполняется" И Состояние.Прогресс <> Неопределено Тогда
		Индикатор = Состояние.Прогресс.Процент;
		СтрокаСостояния = Состояние.Прогресс.Текст;
	КонецЕсли;

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

&НаКлиенте
Процедура ПриЗавершенииЗадания(Результат, ДополнительныеПараметры) Экспорт

	Если Результат = Неопределено Тогда
		СтрокаСостояния = НСтр("ru = 'Задание отменено'");
		Возврат;
	КонецЕсли;

	Если Результат.Статус = "Ошибка" Тогда
		СтрокаСостояния = НСтр("ru = 'Задание завершено с ошибкой'");
		ОбщегоНазначенияКлиент.СообщитьПользователю(Результат.КраткоеПредставлениеОшибки);
	ИначеЕсли Результат.Статус = "Выполнено" Тогда
		Индикатор = 100;
		Обработано = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);
		СтрокаСостояния = СтрШаблон(НСтр("ru = 'Готово, отобрано элементов: %1'"), Обработано.Количество());
	КонецЕсли;

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

Параметр ОповещениеОПрогрессеВыполнения появился в БСП не сразу. Если в вашей версии его нет, используйте обработчик ожидания: каждые 1–2 секунды вызывайте серверную функцию, которая читает ДлительныеОперации.ПрочитатьПрогресс(ИдентификаторЗадания), и выводите процент на форму; в оповещении о завершении отключайте обработчик.

Если стандартное окно ожидания устраивает, достаточно ВыводитьОкноОжидания = Истина — БСП сама покажет текст прогресса. Дорабатывать общую форму длительной операции расширением ради индикатора я не советую: она меняется от версии к версии БСП, и правка начнёт ломаться при обновлениях.

Что происходит в фоне: важные детали

ВопросОтвет
Под каким пользователем работает заданиеПод тем же, что запустил: права те же
Видны ли данные формыНет. Всё нужное передавайте в ПараметрыВыполнения — простыми значениями
Можно ли открыть форму или задать вопрос из фонаНет: клиентских методов в фоне нет
Как вывести сообщения пользователюОбщегоНазначения.СообщитьПользователю в фоне — сообщения будут получены клиентом вместе с результатом
Что с транзакциямиДлинную обработку разбивайте на порции со своими транзакциями, чтобы не держать блокировки
Что будет при закрытии формыЗадание продолжит работу; при необходимости отменяйте его через ДлительныеОперации.ОтменитьВыполнениеЗадания

Типичные ошибки

  • Обработка открыта из файла. Фоновое задание завершается с ошибкой: обработка не найдена. Её нужно зарегистрировать в справочнике дополнительных обработок и открывать оттуда.
  • Поиск обработки по наименованию. Работает до первого переименования. Используйте ссылку, переданную в форму.
  • Передача объектов в параметрах. Ссылки, строки, числа, структуры и массивы из них — можно. Объекты, формы и данные формы — нет.
  • Прогресс на каждой итерации. Задание замедляется, клиент получает сотни сообщений. Сообщайте только при изменении процента или раз в N элементов.
  • Синхронное выполнение в отладке. Без ЗапуститьВФоне = Истина задание может выполниться в текущем сеансе и «работать», хотя в фоне упадёт из-за прав или безопасного режима.
  • Тяжёлая обработка в одной транзакции. Блокировки держатся минутами, у пользователей — ожидания и ошибки.
Фоновое задание не ускоряет алгоритм — оно освобождает пользователя. Если обработка идёт час, сначала стоит разобраться, почему.

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

Итог

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