При разработке асинхронного функционала в 1С разработчики нередко сталкиваются с ситуацией: при запуске процедуры через менеджер фоновых заданий платформа генерирует исключение «Слишком много фактических параметров для метода фонового задания». При этом разработчик уверен, что передает ровно один параметр — объект типа Массив. Разберем механизм работы платформы, выясним причину ошибки и рассмотрим правильные варианты ее устранения.
Проанализируем синтаксис метода ФоновыеЗадания.Выполнить. Второй параметр метода имеет тип Массив. Распространенное заблуждение заключается в том, что разработчик воспринимает этот массив как единый аргумент, который целиком поступит в фоновую процедуру.
На самом деле платформа устроена иначе: переданный массив служит списком аргументов для вызываемой процедуры. Каждый элемент массива передается в качестве отдельного позиционного аргумента. Если в массиве содержится два элемента, платформа пытается вызвать процедуру общего модуля с двумя параметрами:
// Передаем массив из двух элементов:
Парам = Новый Массив;
Парам.Добавить(ЗнВСтрВн);
Парам.Добавить(ПутьКФайлу);
ФоновыеЗадания.Выполнить("АсинхронныеОбработчики.ЗаполнитьТЧ", Парам);
Если в общем модуле процедура объявлена с одним аргументом:
Процедура ЗаполнитьТЧ(ПараметрыЗадания) Экспорт
// ...
КонецПроцедуры
то платформа пытается передать два значения в процедуру, принимающую только одно, и закономерно возвращает ошибку о превышении количества фактических параметров.
Посмотрим на самое простое решение проблемы. Если логика процедуры заранее известна и количество параметров фиксировано, достаточно привести объявление процедуры в соответствие с количеством элементов в массиве вызова:
// В общем модуле АсинхронныеОбработчики (с признаком Сервер):
Процедура ЗаполнитьТЧ(ЗнВСтрВн, ПутьКФайлу) Экспорт
// Полученные аргументы соответствуют элементам переданного массива
СтрокаТЗ = ЗначениеИзСтрокиВнутр(ЗнВСтрВн);
// Дальнейшая обработка файла...
КонецПроцедуры
При таком подходе первый элемент массива Парам[0] попадает в параметр ЗнВСтрВн, а второй Парам[1] — в параметр ПутьКФайлу. Ошибка исчезает.
Рассмотрим подход, который считается стандартом разработки в экосистеме 1С. Когда процедура требует передачи трех и более значений или ее сигнатура может расширяться в будущем, передавать множество позиционных параметров неудобно. Рекомендуется принимать в процедуре один универсальный параметр — структуру.
Для этого упакуем все необходимые данные в объект Структура, а затем поместим эту структуру как единственный элемент во внешний массив параметров запуска:
// Формируем структуру параметров
ПараметрыЗадания = Новый Структура;
ПараметрыЗадания.Вставить("ПутьКФайлу", ПутьКФайлу);
ПараметрыЗадания.Вставить("СтрокаДанных", ДанныеСтроки);
ПараметрыЗадания.Вставить("АдресРезультата", АдресХранилища);
// Оборачиваем структуру в массив параметров вызова
ПараметрыВызова = Новый Массив;
ПараметрыВызова.Добавить(ПараметрыЗадания);
// Запуск фонового задания
ФоновыеЗадания.Выполнить("АсинхронныеОбработчики.ЗаполнитьТЧ",
ПараметрыВызова,
Новый УникальныйИдентификатор,
"Заполнение ТЧ");
В общем модуле процедура принимает ровно один аргумент:
Процедура ЗаполнитьТЧ(ПараметрыЗадания) Экспорт
ПутьКФайлу = ПараметрыЗадания.ПутьКФайлу;
ДанныеСтроки = ПараметрыЗадания.СтрокаДанных;
// Выполнение алгоритма...
КонецПроцедуры
Этот способ исключает ошибки несоответствия аргументов и делает программный код удобным для чтения и поддержки.
Если в силу ограничений существующей архитектуры сигнатуру процедуры менять нельзя, и она обязательно должна принимать один параметр типа Массив, применим обертку массива в массив:
// Внутренний массив с рабочими данными
МассивДанных = Новый Массив;
МассивДанных.Добавить(ЗнВСтрВн);
МассивДанных.Добавить(ПутьКФайлу);
// Внешний массив параметров для платформенного метода
ПараметрыВызова = Новый Массив;
ПараметрыВызова.Добавить(МассивДанных);
ФоновыеЗадания.Выполнить("АсинхронныеОбработчики.ЗаполнитьТЧ", ПараметрыВызова);
В этом случае платформа распакует внешний массив, увидит ровно один элемент (наш МассивДанных) и передаст его в единственную переменную процедуры ЗаполнитьТЧ(МассивДанных).
Проанализируем задачу возврата данных. Фоновое задание выполняется в изолированном сеансе, поэтому оператор Возврат применить невозможно — процедура фонового задания обязана быть именно процедурой, а не функцией.
Для передачи результата обратно в вызывающий сеанс используем временное хранилище:
АдресХранилища = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор);
АдресХранилища в параметрах задания.
ПоместитьВоВременноеХранилище(РезультатОбработки, ПараметрыЗадания.АдресРезультата);
ПолучитьИзВременногоХранилища(АдресХранилища).СтрокаТаблицыЗначений вызовет исключение. Вместо устаревшего метода ЗначениеВСтрокуВнутр предпочтительно выгружать нужные поля строки в Структура или передавать таблицу целиком.Экспорт, а сам модуль не должен быть глобальным.Парам2 = Неопределено), передача меньшего числа аргументов допустима, но передача большего числа все равно приведет к ошибке.