

Длительные одно и многопоточные операции в 1С.
Использование в разработке, (с рабочим примером на GitHub).
25.03.2025
Seredkin Sergey
(developer SPS)
Vybor OBD
Voronezh, Lipetsk Russia
Обзор
Длительные операции это одна из многих возможностей функциональности разработанной в БСП. Если вы пишите код и в нем есть операции большого объема по обработки объектов метаданных будь это документы или справочники. То используя этот код пользователь при нажатии кнопки увидит крутящийся кружок и будет вынужден ждать окончания выполнения кода, а если вы не вывести на свою форму отражение выполнения в виде “прогресса” то вообще будет непонятно идет процесс или он завис по каким либо причинам.
Использование длительных операции позволяет этого избежать так как они выполняются в фоне и позволяют ожидать завершения процесса выполняя другие действия.
На рис 1.1, 1.2 видно как запущены одновременно две разные операции которые не заблокировали работу пользователя после запуска первой обработки.
рис 1.1

Рис 1.1

рис 1.2
На рисунке выше, мы видим выполнение одно поточных длительных операций, но есть возможность разделить фоновый процесс на потоки и выполнять операцию в потоках, это позволит увеличить производительность операции с большим объемом данных.
Пора перейти к главному как это все реализовать!
Основная схема реализации
Для использования длительных однопоточных и многопоточных операций нам понадобятся:
1.1 Внешняя обработка в модули формы которой разместим два клиентских метода и один серверный.
1.2 Расширение со своим общим модулем который назовем “Длительные Операции” в нем расположим саму длительную операцию
1.3 Общие модули такие как “ДлительныеОперации”, “ДлительныеОперацииКлиент’” .
Однопоточная реализация
Обработка .
Создаем обработку на ней Форму, которая имеет поля дат для выбора документов за период, идентификатор формы для передачи в Хранилище ну и конечно команды которые активируют клиентские процедуры расположенные в модуле объекта формы.
В этой обработке я расположил код как для однопоточной, так и для многопоточной обработки длительной операции.

Методы модуля объекта формы
Если открыть ИТС на тему длительные операции там и приводится пример одно поточной реализации, собственно оттуда я взял этапность и доработал код.
Что касается многопоточных то на ИТС не нашел примера .
На рис 2.1 эти методы.
«ВыполнитьОперацию»
«НачатьПроведениеДокументовПТ»
«ПриЗавершениеДлительнойОперации».
Процедура1 запускает Функцию2 и ожидает завершение процесса фонового задания, чтобы передать управление Процедуре3.
В свою очередь Функция2 запускает саму длительную операцию которую я создал в общим модули расширения.
Длительную операцию можно также создавать и модуле менеджера модули обработки но я сторонник расположения разработанного кода, максимально в общих модулях расширения.
На рис 2.2 приведен код процедур и функций.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Объект.УникальныйИдентификатор = Новый УникальныйИдентификатор();
КонецПроцедуры
////Однопоточные операции
//Процедура1
&НаКлиенте
Процедура ВыполнитьОперацию(Команда)
Элементы.СообщениеФорма.ВыделенныйТекст = "";
ЭтотОбъект.ОбновитьОтображениеДанных();
ДлительнаяОперация = НачатьПроведениеДокументовПТ(Объект.датаН,КонецДня(Объект.датаК),
Объект.УникальныйИдентификатор);
// 2. Подключение обработчика завершения фонового задания.
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ПараметрыОжидания.Заголовок = "Фоновое выполнение длительных операций";
ПараметрыОжидания.ВыводитьПрогрессВыполнения = Истина;
ПараметрыОжидания.Интервал = 2;
ПараметрыОжидания.ВыводитьСообщения = Истина;
Оповещение = Новый ОписаниеОповещения("ПриЗавершенииДлительнойОперации", ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, Оповещение, ПараметрыОжидания);
КонецПроцедуры
//Функция2
&НаСервере
Функция НачатьПроведениеДокументовПТ(датаН,датаК,УникальныйИдентификатор)
//"здесь процедура общего модуля которая будет выполняться в ввиде фонового задания"
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияФункции(УникальныйИдентификатор);
Возврат ДлительныеОперации.ВыполнитьФункцию(ПараметрыВыполнения,
"sps_ДлительныеОперации.ГрупповоеПроведениеДокументов"
,"ПТ",датаН, датаК);
КонецФункции
//Процедура3
&НаКлиенте
Процедура ПриЗавершенииДлительнойОперации(Результат, ДополнительныеПараметры) Экспорт
КоличествоПерепроведенныхПТ = 0;
Если Результат = Неопределено Тогда // Пользователь отменил задание.
Возврат;
КонецЕсли;
Если Результат.Статус = "Ошибка" Тогда
СтандартныеПодсистемыКлиент.ВывестиИнформациюОбОшибке(Результат.ИнформацияОбОшибке);
Возврат;
КонецЕсли;
КоличествоПерепроведенныхПТ = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);
УдалитьИзВременногоХранилища(Результат.АдресРезультата);
Элементы.СообщениеФорма.ВыделенныйТекст = "Перепроведено " + КоличествоПерепроведенныхПТ
+ " документов";
ЭтотОбъект.ОбновитьОтображениеДанных();
КонецПроцедуры
////Многопоточные операции
&НаКлиенте
Процедура ВыполнитьМногопоточнуюОперацию(Команда)
ДлительнаяОперация = НачатьМногопоточноеПроведениеДокументовПТ(Объект.датаН,КонецДня(Объект.датаК),
Объект.УникальныйИдентификатор,Объект.Потоков);
// 2. Подключение обработчика завершения фонового задания.
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ПараметрыОжидания.Заголовок = "Фоновое выполнение длительных операций";
ПараметрыОжидания.ВыводитьОкноОжидания = Истина;
ПараметрыОжидания.ВыводитьПрогрессВыполнения = Истина;
ПараметрыОжидания.Интервал = 2;
ПараметрыОжидания.ВыводитьСообщения = Истина;
Оповещение = Новый ОписаниеОповещения("ПриЗавершенииДлительнойМногопоточнойОперации", ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, Оповещение, ПараметрыОжидания);
КонецПроцедуры
&НаКлиенте
Процедура ПриЗавершенииДлительнойМногопоточнойОперации(Результат, ДополнительныеПараметры) Экспорт
КоличествоПерепроведенных = 0;
Если Результат = Неопределено Тогда // Пользователь отменил задание.
Возврат;
КонецЕсли;
Если Результат.Статус = "Ошибка" Тогда
СтандартныеПодсистемыКлиент.ВывестиИнформациюОбОшибке(Результат.ИнформацияОбОшибке);
Возврат;
КонецЕсли;
//КоличествоПерепроведенных = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);
УдалитьИзВременногоХранилища(Результат.АдресРезультата);
КонецПроцедуры
&НаСервере
Функция НачатьМногопоточноеПроведениеДокументовПТ(датаН,датаК,УникальныйИдентификатор,колвоПотоков)
//"здесь процедура общего модуля будет выполняться в ввиде фонового задания разделенного на потоки"
НомерПотока = 1;
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(Новый УникальныйИдентификатор);
ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = 'Выполнение многопоточной функции'");
ПараметрыВыполнения.ОжидатьЗавершение = 0;
ТЗобработки = ПолучитьТзДляМногопоточнойОперации(датаН,датаК);
ЧислоСтрокВТаблице = ТЗобработки.Количество();
ВсегоПотоков = колвоПотоков;
РазмерПорции = Цел(ЧислоСтрокВТаблице/ВсегоПотоков);
НачальныйИндексПорции = 0;
КонечныйИндексПорции = РазмерПорции - 1;
МассивЗаданий = Новый Массив;
МассивАдресовВХранилище = Новый Массив;
ЭтоПоследнийПоток = Ложь;
ПараметрыМетода = Новый Соответствие;
Пока НомерПотока <= колвоПотоков Цикл
ТЗПотока = Новый ТаблицаЗначений;
ТЗПотока = ТЗобработки.СкопироватьКолонки();
Если НомерПотока = ВсегоПотоков Тогда
ЭтоПоследнийПоток = Истина;
КонечныйИндексПорции = ЧислоСтрокВТаблице - 1;
КонецЕсли;
Для Инд = НачальныйИндексПорции По КонечныйИндексПорции Цикл
ЗаполнитьЗначенияСвойств(ТЗПотока.Добавить(), ТЗобработки[Инд]);
КонецЦикла;
АдресВХранилище = ПоместитьВоВременноеХранилище(Неопределено);
МассивАдресовВХранилище.Добавить(АдресВХранилище);
КодПотока = "Поток" + НомерПотока;
ПараметрыПотока = Новый Структура;
ПараметрыПотока.Вставить("ТЗПотока", ТЗПотока);
ПараметрыПотока.Вставить("КомментарийДокумента", "Опа!");
ПараметрыПотока.Вставить("КодПотока", "Поток" + НомерПотока);
ПараметрыПотока.Вставить("ВсегоПотоков", ВсегоПотоков);
ПараметрыПотокаМассив = Новый Массив;
ПараметрыПотокаМассив.Добавить(ПараметрыПотока);
ПараметрыПотокаМассив.Добавить(АдресВХранилище);
ПараметрыМетода.Вставить(КодПотока, ПараметрыПотокаМассив);
Если ЭтоПоследнийПоток Тогда
Прервать;
КонецЕсли;
НачальныйИндексПорции = НачальныйИндексПорции + РазмерПорции;
КонечныйИндексПорции = КонечныйИндексПорции + РазмерПорции ;
номерПотока = номерПотока + 1;
КонецЦикла;
Возврат ДлительныеОперации.ВыполнитьФункциюВНесколькоПотоков(
"sps_ДлительныеОперации.ГрупповоеМногопоточноеПроведениеДокументов",
ПараметрыВыполнения,
ПараметрыМетода);
КонецФункции
Функция ПолучитьТзДляМногопоточнойОперации(датаН,датаК)
ТЗ = Новый ТаблицаЗначений();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслуг.Ссылка КАК Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Дата МЕЖДУ &датаН И &датаК
| И РеализацияТоваровУслуг.ПометкаУдаления = Ложь";
Запрос.УстановитьПараметр("датаК", датаК);
Запрос.УстановитьПараметр("датаН", датаН);
РезультатЗапроса = Запрос.Выполнить();
ТЗ = РезультатЗапроса.Выгрузить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
возврат ТЗ;
Конецфункции
Рис 2.1
Описание параметров и функций / процедур приведенных в коде.
Приведу кратко для понимания не вдаваясь в детали.
В процедуре «ВыполнитьОперацию» идет запуск длительной операции
«НачатьПроведениеПТ()» передавая туда параметры.
Происходит вывод картинки выполнения длительной операции, «ПараметрыОжидания.ВыводитьПрогрессВыполнения = Истина»
Выведет отображение хода выполнения в процентах
«Оповещение = Новый ОписаниеОповещения(«ПриЗавершенииДлительнойОперации», ЭтотОбъект);» выведет оповещение пользователю по завершению в методе «ПриЗавершенииДлительнойОперации»
«ДлительныеОперацииКлиент.ОжидатьЗавершение()» ожидает завершение фонового задания.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Объект.УникальныйИдентификатор = Новый УникальныйИдентификатор();
КонецПроцедуры
////Однопоточные операции
&НаКлиенте
Процедура ВыполнитьОперацию(Команда)
Элементы.СообщениеФорма.ВыделенныйТекст = "";
ЭтотОбъект.ОбновитьОтображениеДанных();
ДлительнаяОперация = НачатьПроведениеДокументовПТ(Объект.датаН,КонецДня(Объект.датаК),
Объект.УникальныйИдентификатор);
// 2. Подключение обработчика завершения фонового задания.
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ПараметрыОжидания.Заголовок = "Фоновое выполнение длительных операций";
ПараметрыОжидания.ВыводитьПрогрессВыполнения = Истина;
ПараметрыОжидания.Интервал = 2;
ПараметрыОжидания.ВыводитьСообщения = Истина;
Оповещение = Новый ОписаниеОповещения("ПриЗавершенииДлительнойОперации", ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, Оповещение, ПараметрыОжидания);
КонецПроцедуры
&НаСервере
Функция НачатьПроведениеДокументовПТ(датаН,датаК,УникальныйИдентификатор)
//"здесь процедура общего модуля которая будет выполняться в ввиде фонового задания"
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияФункции(УникальныйИдентификатор);
Возврат ДлительныеОперации.ВыполнитьФункцию(ПараметрыВыполнения,
"sps_ДлительныеОперации.ГрупповоеПроведениеДокументов"
,"ПТ",датаН, датаК);
КонецФункции
&НаКлиенте
Процедура ПриЗавершенииДлительнойОперации(Результат, ДополнительныеПараметры) Экспорт
КоличествоПерепроведенныхПТ = 0;
Если Результат = Неопределено Тогда // Пользователь отменил задание.
Возврат;
КонецЕсли;
Если Результат.Статус = "Ошибка" Тогда
СтандартныеПодсистемыКлиент.ВывестиИнформациюОбОшибке(Результат.ИнформацияОбОшибке);
Возврат;
КонецЕсли;
КоличествоПерепроведенныхПТ = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);
УдалитьИзВременногоХранилища(Результат.АдресРезультата);
Элементы.СообщениеФорма.ВыделенныйТекст = "Перепроведено " + КоличествоПерепроведенныхПТ
+ " документов";
ЭтотОбъект.ОбновитьОтображениеДанных();
КонецПроцедуры
В процедуре «ПриЗавершенииДлительнойОперации(Результат, Дополнительные Параметры) Экспорт» , получаем из хранилища результат выполнения длительной операции в моем случае это количество пере-проведенных документов.
В хранилище данные помещаются с использование передачи параметра «УникальныйИдентификатор» который используется для создание хранилища с уникальным адресом куда потом помещается результат получаемый в длительной операции .
После получения данных хранилище с данным адресом желательно очищать для освобождения памяти занятой хранилищем.
Запуск Длительной операции и сама длительная операция.
Теперь собственно о самой длительной операции - вот так она запускается:
Используем «ДлительныеОперации.ВыполнитьФункцию()», в нее передаем название самой функции или процедуры, в нашем случае это функция Общего Модуля расширения «spsДлительныеОперации.ГрупповоеПроведениеДокументов» и дополнительных параметров которых может быть до 7.
На рис 2.3 приведен код общего модуля с длительными операциями.
Функция ГрупповоеПроведениеДокументов(ТипДок,Начало_периода,Окончание_периода) Экспорт
Перепроведено_количество = 0;
КоличествоДляОбработки =0;
Если типДок = "ПТ" Тогда
ВыборкаК = Документы.ПриобретениеТоваровУслуг.Выбрать(начало_периода, окончание_периода);
Выборка = Документы.ПриобретениеТоваровУслуг.Выбрать(начало_периода, окончание_периода);
ИначеЕсли типДок = "РТУ" Тогда
ВыборкаК = Документы.РеализацияТоваровУслуг.Выбрать(начало_периода, окончание_периода);
Выборка = Документы.РеализацияТоваровУслуг.Выбрать(начало_периода, окончание_периода);
КонецЕсли;
Пока ВыборкаК.Следующий() Цикл
КоличествоДляОбработки = КоличествоДляОбработки +1;
КонецЦикла;
Если КоличествоДляОбработки > 0 Тогда
Дельта = Окр(100/КоличествоДляОбработки,1);
Иначе
Дельта =0;
КонецЕсли;
ПроцентВыполнения = 0;
Описание = "Идет перепроведение документов";
Пока Выборка.Следующий() Цикл
ПроцентВыполнения = ПроцентВыполнения + Дельта;
Попытка
ДокОбъект = Выборка.ПолучитьОбъект();
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
Перепроведено_количество = Перепроведено_количество +1 ;
ДлительныеОперации.СообщитьПрогресс(Окр(ПроцентВыполнения, 0), Описание);
исключение
КонецПопытки;
КонецЦикла;
возврат Перепроведено_количество ;
КонецФункции
Функция ГрупповоеМногопоточноеПроведениеДокументов(Поток,Адрес) Экспорт
Перепроведено_количество = 0;
КоличествоДокументов = Поток.ТЗПотока.Количество();
Дельта = Окр(100/КоличествоДокументов,1);
ПроцентВыполнения = 0;
Описание = "Идет перепроведение документов поток " + Поток.КодПотока;
Для каждого эл ИЗ Поток.ТЗПотока Цикл
ПроцентВыполнения = ПроцентВыполнения + Дельта;
перепроведено_количество = перепроведено_количество +1;
Попытка
ДокОбъект = эл.ссылка.ПолучитьОбъект();
ДокОбъект.Комментарий = ДокОбъект.Комментарий + " ..." + Поток.КодПотока;
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
ДлительныеОперации.СообщитьПрогресс(Окр(ПроцентВыполнения, 0), Описание);
исключение
КонецПопытки;
КонецЦикла;
возврат Перепроведено_количество ;
КонецФункции
Рис 2.3
Многопоточные длительные операции
Процедуры и функции многопоточной операции
&НаКлиенте
Процедура ВыполнитьМногопоточнуюОперацию(Команда)
ДлительнаяОперация = НачатьМногопоточноеПроведениеДокументовПТ(Объект.датаН,КонецДня(Объект.датаК),
Объект.УникальныйИдентификатор,Объект.Потоков);
// 2. Подключение обработчика завершеня фонового задания.
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ПараметрыОжидания.Заголовок = "Фоновое выполнение длительных операций";
ПараметрыОжидания.ВыводитьОкноОжидания = Истина;
ПараметрыОжидания.ВыводитьПрогрессВыполнения = Истина;
ПараметрыОжидания.Интервал = 2;
ПараметрыОжидания.ВыводитьСообщения = Истина;
Оповещение = Новый ОписаниеОповещения("ПриЗавершенииДлительнойМногопоточнойОперации", ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, Оповещение, ПараметрыОжидания);
КонецПроцедуры
&НаКлиенте
Процедура ПриЗавершенииДлительнойМногопоточнойОперации(Результат, ДополнительныеПараметры) Экспорт
КоличествоПерепроведенных = 0;
Если Результат = Неопределено Тогда // Пользователь отменил задание.
Возврат;
КонецЕсли;
Если Результат.Статус = "Ошибка" Тогда
СтандартныеПодсистемыКлиент.ВывестиИнформациюОбОшибке(Результат.ИнформацияОбОшибке);
Возврат;
КонецЕсли;
//КоличествоПерепроведенных = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);
УдалитьИзВременногоХранилища(Результат.АдресРезультата);
КонецПроцедуры
Процедуры «ВыполнитьМногопоточнуюОперацию()» и «ПриЗавершенииДлительНойМногопоточнойОперации()» такие же по функционалу, как и у однопоточной!, поэтому не будем их рассматривать, а вот функция «НачатьМногопоточноеПроведениеДокументовПТ()» сильно различается.
Разбор функционала многопоточной функции (код приведен на рис 3.1)
&НаСервере
Функция НачатьМногопоточноеПроведениеДокументовПТ(датаН,датаК,УникальныйИдентификатор,колвоПотоков)
//"здесь процедура общего модуля будет выполняться в ввиде фонового задания разделенного на потоки"
НомерПотока = 1;
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(Новый УникальныйИдентификатор);
ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = 'Выполнение многопоточной функции'");
ПараметрыВыполнения.ОжидатьЗавершение = 0;
ТЗобработки = ПолучитьТзДляМногопоточнойОперации(датаН,датаК);
ЧислоСтрокВТаблице = ТЗобработки.Количество();
ВсегоПотоков = колвоПотоков;
РазмерПорции = Цел(ЧислоСтрокВТаблице/ВсегоПотоков);
НачальныйИндексПорции = 0;
КонечныйИндексПорции = РазмерПорции - 1;
МассивЗаданий = Новый Массив;
МассивАдресовВХранилище = Новый Массив;
ЭтоПоследнийПоток = Ложь;
ПараметрыМетода = Новый Соответствие;
Пока НомерПотока <= колвоПотоков Цикл
ТЗПотока = Новый ТаблицаЗначений;
ТЗПотока = ТЗобработки.СкопироватьКолонки();
Если НомерПотока = ВсегоПотоков Тогда
ЭтоПоследнийПоток = Истина;
КонечныйИндексПорции = ЧислоСтрокВТаблице - 1;
КонецЕсли;
Для Инд = НачальныйИндексПорции По КонечныйИндексПорции Цикл
ЗаполнитьЗначенияСвойств(ТЗПотока.Добавить(), ТЗобработки[Инд]);
КонецЦикла;
АдресВХранилище = ПоместитьВоВременноеХранилище(Неопределено);
МассивАдресовВХранилище.Добавить(АдресВХранилище);
КодПотока = "Поток" + НомерПотока;
ПараметрыПотока = Новый Структура;
ПараметрыПотока.Вставить("ТЗПотока", ТЗПотока);
ПараметрыПотока.Вставить("КомментарийДокумента", "Опа!");
ПараметрыПотока.Вставить("КодПотока", "Поток" + НомерПотока);
ПараметрыПотока.Вставить("ВсегоПотоков", ВсегоПотоков);
ПараметрыПотокаМассив = Новый Массив;
ПараметрыПотокаМассив.Добавить(ПараметрыПотока);
ПараметрыПотокаМассив.Добавить(АдресВХранилище);
ПараметрыМетода.Вставить(КодПотока, ПараметрыПотокаМассив);
Если ЭтоПоследнийПоток Тогда
Прервать;
КонецЕсли;
НачальныйИндексПорции = НачальныйИндексПорции + РазмерПорции;
КонечныйИндексПорции = КонечныйИндексПорции + РазмерПорции ;
номерПотока = номерПотока + 1;
КонецЦикла;
рис 3.1
Код для получение данных для обработки в длительной многопоточной операции приведен на рис 3.4
Функция ПолучитьТзДляМногопоточнойОперации(датаН,датаК)
ТЗ = Новый ТаблицаЗначений();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслуг.Ссылка КАК Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Дата МЕЖДУ &датаН И &датаК
| И РеализацияТоваровУслуг.ПометкаУдаления = Ложь";
Запрос.УстановитьПараметр("датаК", датаК);
Запрос.УстановитьПараметр("датаН", датаН);
РезультатЗапроса = Запрос.Выполнить();
ТЗ = РезультатЗапроса.Выгрузить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
возврат ТЗ;
КонецФункции
Рис 3.4
Что происходит в коде функции «НачатьМногопоточноеПроведениеДокументов» давайте разберем пошагово
Шаг1 - С помощью функции «ПолучитьТЗдляМногопоточнойОперации()» мы готовим список ссылок документов которых будем обрабатывать.
Шаг 2 - В зависимости от количества потоков разбиваем эту таблицу значений на более мелкие таблицы значений.
Шаг 3 - Помещаем эти таблицы в Структуру и туда же размещаем дополнительные параметры такие как к примеру комментарий,«НомерКодаПотока», «КоличествоПотоков» и т.д. Но так как у нас несколько таких структур будет несколько ТЗ своя для каждого потока, то помещаем эти структуры в Массив.
Шаг - 4 Запускаем многопоточную операцию передав в нее в виде параметров ПараметрыВыполнения (Уникальный идентификатор), Название длительной операции но и массив о котором шла речь.
Возврат ДлительныеОперации.ВыполнитьФункциюВНесколькоПотоков(
"sps_ДлительныеОперации.ГрупповоеМногопоточноеПроведениеДокументов",
ПараметрыВыполнения,
ПараметрыМетода);
Функция «ВыполнитьФункциюВНесколькоПотоков» запустит основное фоновое задание и начнет его выполнять в потоках, на рис ниже это хорошо видно.
Когда функция модуля расширения получит управление то в параметрах будет вся необходимая информация для ее выполнения параметр - Поток используем «Поток.ТЗПотока» и т.д.
Функция ГрупповоеМногопоточноеПроведениеДокументов(Поток,Адрес) Экспорт
Перепроведено_количество = 0;
КоличествоДокументов = Поток.ТЗПотока.Количество();
Дельта = Окр(100/КоличествоДокументов,1);
ПроцентВыполнения = 0;
Описание = "Идет перепроведение документов поток " + Поток.КодПотока;
Для каждого эл ИЗ Поток.ТЗПотока Цикл
ПроцентВыполнения = ПроцентВыполнения + Дельта;
перепроведено_количество = перепроведено_количество +1;
Попытка
ДокОбъект = эл.ссылка.ПолучитьОбъект();
ДокОбъект.Комментарий = ДокОбъект.Комментарий + " ..." + Поток.КодПотока;
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
ДлительныеОперации.СообщитьПрогресс(Окр(ПроцентВыполнения, 0), Описание);
исключение
КонецПопытки;
КонецЦикла;
возврат Перепроведено_количество ;
Фрагменты выполнения многопоточной операции.


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

Надеюсь использование примера этого кода поможет Вам успешно реализовать механизм длительных операций.
Скачать код можно с GitHuB вод ссылка https://github.com/Sergey-Seredkin/LongOperationsIn1C.git
Также в виде варианта можно залить этот код в виде расширения на свой компьютер.
Для этого необходимо установить 1C “Enterprise Development Tools”,
— это современная расширяемая среда разработки прикладных решений. Она создана на основе свободной интегрированной среды разработки модульных кроссплатформенных приложений Eclipse.
После установки она выглядит вот так.


Создан новый пустой проект можно без труда залить туда данные из удаленного репозитория на GitHub.
Создаем каталог локального репозитория git в моем случае это -
C:\Users\User\git\LongOperationsIn1C .
Открываем проект и выбираем импорт с GitHub клонировать URL.

Затем используя “Далее” двигаемся дальше..

Указываем URL: (Ссылка приведена выше).
Выбираем ветку master.(остальные галочки снимаем) и нажимаем “Далее”

Выбираем локальный репозиторий git нажимаем далее ..

Откроется содержимое удаленного проекта git для переноса отмеченное флажком, жмем далее ..

Используя Далее и “Импорт из существующего проекта Eclipse” будет показано содержимое удаленного репозитория git отмеченное флажком, остается нажать кнопку “Готово”.
В результате в панели Навигатор откроется дерево проекта расширения!

Загрузка выполнена!.
Успешного программирования.