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