1. Вызываем основную функцию где нужно получить результат многопоточной обаботки
&НаСервере Процедура ПолучитьтаблицуПоПараметрам_Многопоточно(парам1) ТЗСтатистикаПродажПоДням = АвтоматизацияПрогноза.ПолучитьТЗСтатистикаПродаж_Многопоточно(парам1,8); КонецПроцедуры
2. В общем модуле, например, получаем основноую таблицу, котороую потом нужно многопоточно обработать
&НаСервере
Функция ПолучитьТЗСтатистикаПродаж_Многопоточно(Параметры=Неопределено) Экспорт
ТЗОбщая = Новый ТаблицаЗначений;
Если Не ЗначениеЗаполнено(Параметры) Тогда
Возврат ТЗОбщая;
КонецЕсли;
//Получаем общую таюлицу для последующей многопоточной обработки
ТЗОбщая = ПолучитьПредварительнуюТаблицу(Параметры);
// определяем максимальное количество потоков
ЧислоСтрокВТаблице = ТЗОбщая.Количество();
//Определяем число потоков
ЧислоПотоков = РегистрыСведений.РегистрКонстант.ПолучитьЗначениеКонстанты("КоличествоПотоковДляРасчетаАвтоПрогноза");
Если Не ЗначениеЗаполнено(ЧислоПотоков) Тогда
ЧислоПотоков = 8;
КонецЕсли;
// объем порции данных для обработки каждым потокомс
РазмерПроции = Цел(ЧислоСтрокВТаблице/ЧислоПотоков);
// массив где будут храниться фоновые задания
МассивЗаданий = Новый Массив;
Для НомерПотока = 1 По ЧислоПотоков Цикл
// определяем индекс для начала обработки данных данным потоком
// разные потоки обрабатывают разные части таблицы
ИндексНачала = (НомерПотока - 1)*РазмерПроции;
Если (НомерПотока = ЧислоПотоков) Тогда
// если это последний поток, то он обрабатывает все оставшиеся данные
// т.к. число потоков может не быть кратно количеству строк в таблице
РазмерПроции = ЧислоСтрокВТаблице-(ЧислоПотоков*РазмерПроции)+РазмерПроции;
КонецЕсли;
// определяем массив параметров для процедуры
НаборПараметров = Новый Массив;
НаборПараметров.Добавить(ТЗОбщая);
НаборПараметров.Добавить(Параметры.ЗапросСтатистики_Склад);
НаборПараметров.Добавить(ИндексНачала);
НаборПараметров.Добавить(РазмерПроции);
// запуск фонового задания
Задание = ФоновыеЗадания.Выполнить("АвтоматизацияПрогноза.ДополнитьДопДанными_Многопоточный", НаборПараметров);
// добавляем задание в массив, что бы потом отследить выполнение
МассивЗаданий.Добавить(Задание);
КонецЦикла;
// проверим результат выполнения фоновых заданий
Если МассивЗаданий.Количество() > 0 Тогда
Попытка
ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);
Исключение
// действия в случае ошибки
Сообщить(ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
Возврат ТЗОбщая;
КонецФункции
3. Вот эта часть будет обрабатывать свои части таблицы значений в паралельных многопоточных потоках
&НаСервере
Процедура ДополнитьДопДанными_Многопоточный(ТЗОбщая, Склад, ИндексНачала, РазмерПроции) Экспорт
//Дополнительные таблицы
Для Сч = 1 По РазмерПроции Цикл
Индекс = ?(Сч=1, ИндексНачала, Индекс+1);
стр = ТЗОбщая[Индекс];
//++Остатки
Запрос = Новый ПостроительЗапроса();
Запрос.Текст =
"ВЫБРАТЬ
| ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
| ЕСТЬNULL(ТоварыНаСкладахОстатки.ВНаличииОстаток, 0) КАК КоличествоНаСкладе,
| &Период КАК ДеньМесяца
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, Номенклатура = &Номенклатура {(Склад = &Склад) КАК Поле2}) КАК ТоварыНаСкладахОстатки";
Запрос.Параметры.Вставить("Номенклатура", стр.Номенклатура);
Запрос.Параметры.Вставить("Период", стр.Период);
Если ЗначениеЗаполнено(Склад) тогда
Запрос.Параметры.Вставить("Склад", Склад);
Запрос.Отбор.Добавить("Поле2");
Запрос.Отбор.Поле2.Значение = Истина;
Запрос.Отбор.Поле2.ВидСравнения = ВидСравнения.Равно;
Запрос.Отбор.Поле2.Использование = Истина;
КонецЕсли;
Запрос.Выполнить();
ТЗОстатки = Запрос.Результат.Выгрузить();
Для каждого ВыборкаДетальныеЗаписи из ТЗОстатки Цикл
стр.Остаток = ВыборкаДетальныеЗаписи.КоличествоНаСкладе;
прервать;
КонецЦикла;
//--Остатки
//++Себестоимость
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СебестоимостьТоваровОстатки.АналитикаУчетаНоменклатуры.Номенклатура КАК НоменклатураСебестоимость,
| СРЕДНЕЕ(ВЫБОР
| КОГДА ЕСТЬNULL(СебестоимостьТоваровОстатки.КоличествоОстаток, 0) > 0
| ТОГДА ЕСТЬNULL(СебестоимостьТоваровОстатки.СтоимостьОстаток, 0) / ЕСТЬNULL(СебестоимостьТоваровОстатки.КоличествоОстаток, 0)
| ИНАЧЕ 0
| КОНЕЦ) КАК СебестоимостьТовара,
| &Период КАК ДеньМесяца
|ИЗ
| РегистрНакопления.СебестоимостьТоваров.Остатки(&Период, АналитикаУчетаНоменклатуры.Номенклатура = &Номенклатура) КАК СебестоимостьТоваровОстатки
|
|СГРУППИРОВАТЬ ПО
| СебестоимостьТоваровОстатки.АналитикаУчетаНоменклатуры.Номенклатура";
Запрос.УстановитьПараметр("Номенклатура", стр.Номенклатура);
Запрос.УстановитьПараметр("Период", стр.Период);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
стр.Себестоимость = ВыборкаДетальныеЗаписи.СебестоимостьТовара;
прервать;
КонецЦикла;
//--Себестоимость
//++ВЗаказах
Запрос = Новый ПостроительЗапроса();
Запрос.Текст =
"ВЫБРАТЬ
| ЗаказыПоставщикамОстатки.Номенклатура КАК Номенклатура,
| СУММА(ЕСТЬNULL(ЗаказыПоставщикамОстатки.ЗаказаноОстаток, 0)) КАК КоличествоВЗаказах,
| СРЕДНЕЕ(ЕСТЬNULL(ВложенныйЗапрос.Цена, 0)) КАК ЦенаИзЗаказа,
| &Период КАК ДеньМесяца
|ИЗ
| РегистрНакопления.ЗаказыПоставщикам.Остатки(&Период, Номенклатура = &Номенклатура {(Склад = &Склад) КАК Поле2}) КАК ЗаказыПоставщикамОстатки
| ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
| ЗаказПоставщикуТовары.Номенклатура КАК Номенклатура,
| СРЕДНЕЕ(ЗаказПоставщикуТовары.Цена) КАК Цена,
| ЗаказПоставщикуТовары.Ссылка КАК Ссылка
| ИЗ
| Документ.ЗаказПоставщику.Товары КАК ЗаказПоставщикуТовары
|
| СГРУППИРОВАТЬ ПО
| ЗаказПоставщикуТовары.Номенклатура,
| ЗаказПоставщикуТовары.Ссылка) КАК ВложенныйЗапрос
| ПО ЗаказыПоставщикамОстатки.Номенклатура = ВложенныйЗапрос.Номенклатура
| И ЗаказыПоставщикамОстатки.ЗаказПоставщику = ВложенныйЗапрос.Ссылка
|
|СГРУППИРОВАТЬ ПО
| ЗаказыПоставщикамОстатки.Номенклатура";
Запрос.Параметры.Вставить("Номенклатура", стр.Номенклатура);
Запрос.Параметры.Вставить("Период", стр.Период);
Если ЗначениеЗаполнено(Склад) тогда
Запрос.Параметры.Вставить("Склад", Склад);
Запрос.Отбор.Добавить("Поле2");
Запрос.Отбор.Поле2.Значение = Истина;
Запрос.Отбор.Поле2.ВидСравнения = ВидСравнения.Равно;
Запрос.Отбор.Поле2.Использование = Истина;
КонецЕсли;
Запрос.Выполнить();
ТЗВЗаказах = Запрос.Результат.Выгрузить();
Для каждого ВыборкаДетальныеЗаписи из ТЗВЗаказах Цикл
стр.ЦенаИзЗаказов = ВыборкаДетальныеЗаписи.ЦенаИзЗаказа;
стр.ВЗаказах = ВыборкаДетальныеЗаписи.КоличествоВЗаказах;
прервать;
КонецЦикла;
//--+ВЗаказах
//++ВДороге
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СебестоимостьТоваровОстатки.АналитикаУчетаНоменклатуры.Номенклатура КАК НоменклатураЕдет,
| СУММА(ЕСТЬNULL(СебестоимостьТоваровОстатки.КоличествоОстаток, 0)) КАК КоличествоЕдет,
| СРЕДНЕЕ(ВЫБОР
| КОГДА ЕСТЬNULL(СебестоимостьТоваровОстатки.КоличествоОстаток, 0) > 0
| ТОГДА ЕСТЬNULL(СебестоимостьТоваровОстатки.СтоимостьОстаток, 0) / ЕСТЬNULL(СебестоимостьТоваровОстатки.КоличествоОстаток, 0)
| ИНАЧЕ 0
| КОНЕЦ) КАК СебестоимостьЕдет,
| &Период КАК ДеньМесяца
|ИЗ
| РегистрНакопления.СебестоимостьТоваров.Остатки(
| &Период,
| РазделУчета = ЗНАЧЕНИЕ(Перечисление.РазделыУчетаСебестоимостиТоваров.ТоварыВПути)
| И АналитикаУчетаНоменклатуры.Номенклатура = &Номенклатура) КАК СебестоимостьТоваровОстатки
|
|СГРУППИРОВАТЬ ПО
| СебестоимостьТоваровОстатки.АналитикаУчетаНоменклатуры.Номенклатура";
Запрос.УстановитьПараметр("Номенклатура", стр.Номенклатура);
Запрос.УстановитьПараметр("Период", стр.Период);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
стр.ВДороге = ВыборкаДетальныеЗаписи.КоличествоЕдет;
прервать;
КонецЦикла;
//--ВДороге
КонецЦикла;
КонецПроцедуры