Имя: Пароль:
1C
 
Помогите распараллелить процедуру
0 Mulber
 
18.04.25
10:05
Доброго всем дня. Нуждаюсь в помощи по распараллеливанию процедуры по 4 фоновых задания (по поставщикам, 4 разом из СписокПоставщиков).Сейчас в цикле последовательно данные получаю: &НаСервере
ЗагрузитьЦеныПоставщиковЭксп
Процедура ЗагрузитьЦеныПоставщиковЭксп(Список, ДанныеПоставщика, ПакетнаяОбработка = Ложь) Экспорт
	
	ТЗ = Новый ТаблицаЗначений;
	ТЗ.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"), "N");
	ТЗ.Колонки.Добавить("MPN", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(100)), "MPN");
	ТЗ.Колонки.Добавить("MPNAPI", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(100)), "MPN API");
	ТЗ.Колонки.Добавить("КоличествоВЗаказе", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 5, ДопустимыйЗнак.Неотрицательный)), "Количество в заказе");
	ТЗ.Колонки.Добавить("ПроизводительВЗаказе", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(0)), "Производитель в заказе"); 
	ТЗ.Колонки.Добавить("Производитель", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(0)), "Производитель");
	ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 5, ДопустимыйЗнак.Неотрицательный)), "Цена");
	ТЗ.Колонки.Добавить("Валюта", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(10)), "Валюта"); 
	ТЗ.Колонки.Добавить("МинКоличествоЗаказа", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10)), "Мин количество заказа");
	ТЗ.Колонки.Добавить("КоличествоВУпаковке", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10)), "Количество в упаковке");
	ТЗ.Колонки.Добавить("НаличиеНаСкладе", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10)), "Наличие на складе");
	ТЗ.Колонки.Добавить("СрокПоставки", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(0)), "Срок поставки");
	ТЗ.Колонки.Добавить("СуммаЗаказа", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 5, ДопустимыйЗнак.Неотрицательный)), "Сумма заказа");
	ТЗ.Колонки.Добавить("ВесПозиции", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 3)), "Вес позиции");
	ТЗ.Колонки.Добавить("ОтветСервера", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(0)), "Ответ сервера");
	ТЗ.Колонки.Добавить("Поставщик", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(0)), "Поставщик");
	
	Если Список.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
		
	СписокПоставщиков = Новый Массив();
	НомераПоставщиков = Новый Массив();
	
	Для Каждого Поставщик Из Список Цикл
		Масс = ПодключениеИЗагрузкаДанныхПоставщиков.СтрРазделить(Поставщик, "~", Истина);
		НомераПоставщиков.Добавить(Масс[0]);
		СписокПоставщиков.Добавить(Масс[1]);
	КонецЦикла;
	
	Для Каждого Поставщик Из СписокПоставщиков Цикл	
		_MPN = "";
		_MAN = "";
		_QTY = "";	
		_TKN = "";
		_RES1 = "";
		_RES2 = "";
		
		Выгрузка = ПодключениеИЗагрузкаДанныхПоставщиков.ПолучитьНастройкиAPIПоставщика(Поставщик);
		
		Если Выгрузка.Количество() = 0 Тогда
			Возврат;
		КонецЕсли;
			
		Принудительно = Не ПакетнаяОбработка;
		
		МассивПартНомеров = Новый Массив();
		
		МассивПартНомеров = ДанныеПоставщика.ВыгрузитьКолонку("MPN");
			
		Сч = 1;
		
		КоличествоПозиций = МассивПартНомеров.Количество();		
		
		Рез = ВыполнитьЗапрос(0, Выгрузка, _MPN, _MAN, _QTY, _TKN, _RES1, _RES2, Сч, Поставщик, Принудительно, СписокПоставщиков, Список, 
							МассивПартНомеров, КоличествоПозиций, ДанныеПоставщика, НомераПоставщиков, ТЗ, ПакетнаяОбработка);
							
		Если Рез = 0 Тогда
			Возврат;
		ИначеЕсли Рез = 1 Тогда
			Продолжить;
		ИначеЕсли Рез = 2 Тогда
			Прервать;
		КонецЕсли;
		
		Рез = ВыполнитьЗапрос(1, Выгрузка, _MPN, _MAN, _QTY, _TKN, _RES1, _RES2, Сч, Поставщик, Принудительно, СписокПоставщиков, Список, 
							МассивПартНомеров, КоличествоПозиций, ДанныеПоставщика, НомераПоставщиков, ТЗ, ПакетнаяОбработка);
							
		Если Рез = 0 Тогда
			Возврат;
		ИначеЕсли Рез = 1 Тогда
			Продолжить;
		ИначеЕсли Рез = 2 Тогда
			Прервать;
		КонецЕсли;
		
		Рез = ВыполнитьЗапрос(2, Выгрузка, _MPN, _MAN, _QTY, _TKN, _RES1, _RES2, Сч, Поставщик, Принудительно, СписокПоставщиков, Список, 
							МассивПартНомеров, КоличествоПозиций, ДанныеПоставщика, НомераПоставщиков, ТЗ, ПакетнаяОбработка);
							
		Если Рез = 0 Тогда
			Возврат;						
		ИначеЕсли Рез = 1 Тогда
			Продолжить;
		ИначеЕсли Рез = 2 Тогда
			Прервать;
		КонецЕсли;
							
	КонецЦикла;
	
КонецПроцедуры
1 программистище
 
18.04.25
15:43
Если у поставщиков не равномерное количество данных, посчитай вхождение, сделай таблицу, назначь веса поставщикам, и равномерно разбей на подсписки, и запускай фоновые с этими списками, в чем проблема то?

по запуску в фоне:
В общем виде процесс запуска и обработки результата длительной операции выглядит следующим образом
   1) Процедура, которая будет исполняться в фоне, располагается в модуле менеджера объекта или в серверном общем модуле
Процедура ВыполнитьДействие(Параметры, АдресРезультата) Экспорт
     ..
     ПоместитьВоВременноеХранилище(Результат, АдресРезультата)
КонецПроцедуры

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

&НаСервере
Функция НачатьВыполнениеНаСервере(
     ПараметрыПроцедуры = Новый Структура
     ..
     ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор)
     ..
     Возврат ДлительныеОперации.ВыполнитьВФоне("Обработка.МояОбработка.ВыполнитьДействие"
     ПараметрыПроцедуры, ПараметрыВыполнения)
КонецФункции

   3) Обработка результата выполнения операции
&НаКлиенте
Процедура ВыполнитьДействиеЗавершение(Результат, ДополнительныеПараметры) Экспорт
     Если Результат = Неопределено Тогда
      Возврат
     КонецЕсли
     Если Результат.Статус ="Ошибка"Тогда
      СтандартныеПодсистемыКлиент.ВывестиИнформациюОбОшибке(Результат.ИнформацияОбОшибке)
      Возврат
     КонецЕсли
     ВывестиРезультат(Результат)
КонецПроцедуры
2 H A D G E H O G s
 
18.04.25
11:18
(1) плохая стратегия сразу раскидывать.

1. Делим список на порции, пофиг какого веса там внутри данные.

2. Выделяем пул фоновых по числу ядер проца -1.

3. Как только фоновое завершается - создаем ему взамен новое фоновое с новой порцией данных.
3 Mulber
 
18.04.25
15:37
Сделал так, вроде работает:
Подробности
Процедура ЗагрузитьЦеныПоставщиковЭксп_Многопоток(Список, ДанныеПоставщика, ПакетнаяОбработка = Ложь) Экспорт
    
    ТЗ = Новый ТаблицаЗначений;
    ТЗ.Колонки.Добавить("НомерСтроки", Новый ОписаниеТипов("Число"), "N");
    ТЗ.Колонки.Добавить("MPN", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(100)), "MPN");
    ТЗ.Колонки.Добавить("MPNAPI", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(100)), "MPN API");
    ТЗ.Колонки.Добавить("КоличествоВЗаказе", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 5, ДопустимыйЗнак.Неотрицательный)), "Количество в заказе");
    ТЗ.Колонки.Добавить("ПроизводительВЗаказе", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(0)), "Производитель в заказе");
    ТЗ.Колонки.Добавить("Производитель", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(0)), "Производитель");
    ТЗ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 5, ДопустимыйЗнак.Неотрицательный)), "Цена");
    ТЗ.Колонки.Добавить("Валюта", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(10)), "Валюта");
    ТЗ.Колонки.Добавить("МинКоличествоЗаказа", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10)), "Мин количество заказа");
    ТЗ.Колонки.Добавить("КоличествоВУпаковке", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10)), "Количество в упаковке");
    ТЗ.Колонки.Добавить("НаличиеНаСкладе", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10)), "Наличие на складе");
    ТЗ.Колонки.Добавить("СрокПоставки", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(0)), "Срок поставки");
    ТЗ.Колонки.Добавить("СуммаЗаказа", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 5, ДопустимыйЗнак.Неотрицательный)), "Сумма заказа");
    ТЗ.Колонки.Добавить("ВесПозиции", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 3)), "Вес позиции");
    ТЗ.Колонки.Добавить("ОтветСервера", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(0)), "Ответ сервера");
    ТЗ.Колонки.Добавить("Поставщик", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(0)), "Поставщик");
    
    Если Список.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
        
    СписокПоставщиков = Новый Массив();
    НомераПоставщиков = Новый Массив();
    
    Для Каждого Поставщик Из Список Цикл
        Масс = ПодключениеИЗагрузкаДанныхПоставщиков.СтрРазделить(Поставщик, "~", Истина);
        НомераПоставщиков.Добавить(Масс[0]);
        СписокПоставщиков.Добавить(Масс[1]);
    КонецЦикла;
    
    ЧислоПараллельныхПотоков = 5;
    МассивЗаданий = Новый Массив;
    
    Для Каждого Поставщик Из СписокПоставщиков Цикл    

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


Всем откликнувшимся спасибо!
Требовать и эффективности, и гибкости от одной и той же программы — все равно, что искать очаровательную и скромную жену... по-видимому, нам следует остановиться на чем-то одном из двух. Фредерик Брукс-младший