kb-personal/src/content/docs/knowledge-base//1. Общие/Длительные операции/Длительная многопоточная операция.md
2025-06-16 21:32:32 +05:00

10 KiB
Raw Blame History

title, slug
title slug
Длительная многопоточная операция 1с-1-общие-длительные-операции/длительная-многопоточная-операция

Определение длительной операции

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

Процедура ИзменитьРеквизитыНоменклатуры(НаборЗаписей) Экспорт
 
	Если Не Пользователи.ЭтоПолноправныйПользователь(Пользователи.ТекущийПользователь()) Тогда
		ТекстСообщения = "Это действие может выполнить только администратор";
		ОбщегоНазначения.СообщитьПользователю(ТекстСообщения);
		Возврат;
	КонецЕсли;
	
	Для Каждого Элемент Из НаборЗаписей Цикл
		
		Об = Элемент.Номенклатура.ПолучитьОбъект();
		Если Об.Заблокирован() Тогда
			Продолжить;
		КонецЕсли;
		
		Попытка 
			Об.Заблокировать();
		Исключение
			ТекстСообщения = СтрШаблон("Не удалось изменить %1. Объект заблокирован", Элемент.Номенклатура);
			ОбщегоНазначения.СообщитьПользователю(ТекстСообщения);
			Продолжить;
		КонецПопытки;
		
		Об.ИспользоватьУпаковки = Истина;
		Об.НаборУпаковок = Элемент.НаборУпаковок;
		Попытка
			Об.Записать();
		Исключение
			ТекстСообщения = СтрШаблон("Не удалось изменить %1. Ошибка записи объекта", Элемент.Номенклатура);
			ОбщегоНазначения.СообщитьПользователю(ТекстСообщения);
			Продолжить;
		КонецПопытки;
		
	КонецЦикла;
	
КонецПроцедуры

Определение клиентских вызовов

image.png Команда «Установить новый набор» выполняет разделение строк ТЧ на равные порции, т.е. создает список наборов, которые будут передаваться в процедуру из шага 1 (Функция «СписокНаборовДанныхДляДлительнойОперации«). Дополнительно инициализируются настройки ожидания и параметры выполняемой процедуры (Функция «ДлительныеОперации«). Также указывается процедура, которая будет выполнена после завершения всех потоков длительной операции

&НаКлиенте
Процедура УстановитьНовыйНабор(Команда)
	
	ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
	ПараметрыОжидания.ВыводитьОкноОжидания = Истина;
	ПараметрыОжидания.ВыводитьСообщения = Истина;
	ПараметрыОжидания.ОповещениеПользователя.Показать = Истина;
	
	СписокНаборов = СписокНаборовДанныхДляДлительнойОперации();
	
	МногопоточнаяОперация = ДлительнаяОперация(УникальныйИдентификатор, СписокНаборов);
	
	ОписаниеОповещения = Новый ОписаниеОповещения("ВыполнитьПоЗавершениюМногопоточнойОперации", ЭтотОбъект);
	
	ДлительныеОперацииКлиент.ОжидатьЗавершение(МногопоточнаяОперация, ОписаниеОповещения, ПараметрыОжидания); 
	
КонецПроцедуры
 
&НаКлиенте
Функция СписокНаборовДанныхДляДлительнойОперации()
 
	НаборЗаписей = Новый Массив;
	
	КоличествоЗаписейНаПоток = Цел(Объект.СписокНоменклатуры.Количество() / КоличествоПотоков) + 1;
	
	СписокНаборов = Новый Массив;
	
	Сч = 1;
	Для Каждого Строка Из Объект.СписокНоменклатуры Цикл
		
		Если Не Строка.НовыйИспользоватьУпаковки Тогда
			Сообщить("Не добавлена строка " + Строка.НомерСтроки);
			Продолжить;
		КонецЕсли;
		
		ПараметрыСтроки = Новый Структура;
		ПараметрыСтроки.Вставить("Номенклатура", Строка.Номенклатура);
		ПараметрыСтроки.Вставить("ИспользоватьУпаковки", Истина);
		ПараметрыСтроки.Вставить("НаборУпаковок", Строка.НовыйНаборУпаковок);
		
		НаборЗаписей.Добавить(ПараметрыСтроки);
		Сч = Сч + 1;
		НужноДобавитьНабор = Истина;
		
		Если Сч % КоличествоЗаписейНаПоток = 0 Тогда
			СписокНаборов.Добавить(НаборЗаписей);
			НаборЗаписей = Новый Массив;
			НужноДобавитьНабор = Ложь;
		КонецЕсли;
		
	КонецЦикла;
	
	Если НужноДобавитьНабор Тогда
		СписокНаборов.Добавить(НаборЗаписей);
	КонецЕсли;
	
	КоличествоЗаписей = 0;
	
	Для Каждого Массив Из СписокНаборов Цикл
		
		КоличествоЗаписей = КоличествоЗаписей + Массив.Количество();
		
	КонецЦикла;	
	
	Возврат СписокНаборов;
	
КонецФункции
 
&НаКлиенте
Процедура ВыполнитьПоЗавершениюМногопоточнойОперации(Задание, ДополнительныеПараметры) Экспорт
	
	Если Задание = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Сообщить(Задание.Статус);
 
КонецПроцедуры

В функции длительная операция необходимо правильно сформировать параметры для метода ДлительныеОперации.ВыполнитьПроцедуруВНесколькоПотоков. Первым аргументом передаем полное имя экспортного метода, который нужно выполнять, вторым — структуру ДлительныеОперации.ПараметрыВыполненияВФоне, а третьим — правильно оформленный набор параметров.

Набор параметров — это соответствие, ключ — произвольный тип, значение — МАССИВ параметров, которые нужно передать в вызываемый метод. Количество параметров — до 7 шт. В примере метод «ИзменитьРеквизитыНоменклатуры» принимает только один параметр, соответственно в значение записи набора параметров мы передаем обернутое в массив значение параметра («ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Набор)

&НаСервере
Функция ДлительнаяОперация(УИД, СписокНаборовДанных)
 
	ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УИД);
	ПараметрыВыполнения.НаименованиеФоновогоЗадания = "Многопоточное изменение реквизитов номенклатуры";
	ПараметрыВыполнения.ЗапуститьВФоне = Истина;
	
	Сч = 1;
	НаборПараметровПроцедуры = Новый Соответствие;
	Для Каждого Набор Из СписокНаборовДанных Цикл
		НаборПараметровПроцедуры.Вставить("Набор №" + Сч, ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(Набор));
		Сч = Сч + 1;
	КонецЦикла;
	
	Возврат ДлительныеОперации.ВыполнитьПроцедуруВНесколькоПотоков(
		"Расш1_ДлительныеОперации.ИзменитьРеквизитыНоменклатуры", 
		ПараметрыВыполнения, НаборПараметровПроцедуры);
	
КонецФункции