Не так давно публиковал статью о многопоточности простым способом, решил продвинуться дальше и внедрить данный функционал в обработку консоли кода не только для обычных форм (разработал давно, использую сам, публиковать не планирую), но и для управляемых. В качестве основы использую все ту же обработку salexdv Консоль кода для управляемых форм, которую я уже модифицировал в статье про объявление методов в консоли.
Идея обработки простая: у нас есть данные, которые нужно обработать в любой последовательности (можно использовать сортировку, но четкая последовательность не важна) и обрабатывать их в один поток слишком долго. Можно написать код для определения этих данных и прочих параметров, а потом обработать в соответствующей функции обработки порции, но уже в несколько потоков за счет использования механизма фоновых заданий. Разумеется, здесь встает ограничение на передачу данных фоновому заданию - данные должны быть сериализуемы. Соответственно, например, результат запроса передавать можно, а выборку из результата запроса - уже нет. Ну и никаких ДокументОбъект, строки должны поддерживать сериализацию XML (должны отсутствовать неподдерживаемые символы) и прочая, и прочая. Вообще, все сериализуемые объекты легко можно подсмотреть в синтакс-помощнике по слову "сериализуется" - их там больше 300, чтобы вы понимали, и наверняка вы найдете то, что не ожидали увидеть в этом списке!
Немного расскажу про механизм вызова кода обработки порций. Собранные данные и дополнительные параметры функции передаются фоновому заданию, чтобы обеспечить тем самым удобство использования с отслеживанием прогресса и параллельной работой с базой 1С во время обработки. Одним из самых удобных видов передаваемых данных может служить Результат запроса. Все это вместе с дополнительными параметрами помещается кодом, написанным вами в тексте определения данных и параметров, в массив ПараметрыВызова, в котором первый элемент - это, собственно, распараллеливаемые данные, а последующие параметры - дополнительные в любом количестве, в разумных пределах, конечно. Последующие параметры передаются в функцию обработки, которую вы пишете на другой вкладке, в непосредственном виде, в то время как данные для обработки - в виде порции с типом Массив. Массив легко переделать в Таблицу Значений, если нужно - в образце, вставляемом при переключении на многопоточность, есть код вызова соответствующей процедуры. При этом вторым параметром функции обработки данных всегда должен следовать АдресРезультата, чтобы можно было в случае необходимости вернуть какие-либо результаты выполнения обработки. Помещать его в массив ПараметрыВызова не нужно, он получается из функции-оркестратора. Чтобы не быть голословным, приведу здесь строчки дополнения кода:
ОсновнойТекст = ОсновнойТекст + Символы.ПС + Символы.Таб + "ПараметрыВызова = Новый Массив;
| ПараметрыВызова.Добавить(ДанныеДляОбработки); // РезультатЗапроса, Массив (в т.ч. Структур) или Таблица значений
| ПараметрыВызова.Добавить(ДополнительныйПараметр1); // сериализуемое значение
| ПараметрыВызова.Добавить(ДополнительныйПараметр2); // сериализуемое значение";
ОчиститьТекст(Истина);
УстановитьТекст(ОсновнойТекст, Неопределено, Истина, Истина);
КодОбработки = КодОбработки + Символы.ПС + "Процедура ОбработкаДанных(ДанныеДляОбработки, АдресРезультата, ДополнительныйПараметр1, ДополнительныйПараметр2) Экспорт
| ДанныеВВидеТаблицы = МВК_ДлительныеОперацииСервер.МассивЗаписейВТаблицуЗначений(ДанныеДляОбработки); // на входе всегда универсальный массив
| Результат = ДанныеДляОбработки; // здесь любой код обработки с получением результата или без
| ПоместитьВоВременноеХранилище(Результат, АдресРезультата); // если хотите, чтобы результаты потоков объединялись в один массив, результат должен быть массивом (сериализуемым, конечно)
|КонецПроцедуры";
ОчиститьТекст(Ложь);
УстановитьТекст(КодОбработки, Неопределено, Ложь, Ложь);
Как видим, в основной код вставляется определение массива ПараметрыВызова, а в код обработки - экспортная процедура ОбработкаДанных. Разумеется, количество дополнительных параметров этого метода должно соответствовать количеству их в массиве ПараметрыВызова. Кстати, для тех, кто до конца не понял, как это работает, есть пример, вызывается из подменю Примеры. Реализована простая проверка и (по возможности) удаление дублей справочника номенклатура.
Что происходит дальше? В фоновом задании вызывается функция-оркестратор, которая управляет обработкой порций также в фоновых заданиях - ВыполнитьФункциюПорциями. Она дробит данные на порции в соответствии с заданными на форме параметрами и запускает, а затем проверяет их обработку. В случае ошибки можно продолжить, но лучше остановиться и передать ее в консоль. Это осуществляется за счет обработки записей журнала регистрации, которые обычно формируются при ошибке в фоновом задании. Таким образом становится возможным следующее:
И если уж совсем углубляться, то в задании по обработке порции запускается метод модуля менеджера обработки ПроизвольнаяФункция, который формирует и подключает временную обработку, наполняя ее модуль объекта кодом обработки порции. Вот такая вот матрешка получается, но главное что это работает!
По ходу выполнения при завершении обработки каждой порции идет оповещение через панель состояния:

Этого удалось добиться благодаря тому же методу, что используется в БСП - обработка сообщений задания через ПолучитьСообщенияПользователю. На скриншоте не видно, но также на эту вкладку добавил кнопку отмены обработки, чтобы можно было передумать. Разумеется, никаких транзакций в фоновых заданиях - отменяется только то, что не успело выполниться.
В том, что касается задействования ресурсов сервера, конечно, не стоит ожидать, что всегда, когда вы укажете 10 потоков, будут полностью задействованы 10 ядер. На простых операциях записи, например, у меня было задействовано 4 ядра, но там ничего не проверялось - это не стандартный сценарий. А вот с указанным выше алгоритмом удалось задействовать почти все ядра процессора:

Что не может не радовать, поскольку операция выполнится максимально быстро. Обратите внимание, что потоков 10, а ядер задействовано больше - это из-за того, что база данных PostgreSQL размещена на том же компьютере, что и сервер 1С, а она также активно работает на таких операциях как поиск ссылок и удаление.
Обратите внимание! Многопоточность методом фоновых заданий доступна только для клиент-серверных информационных баз, поскольку в файловых может одновременно работать только одно фоновое задание. Остальные будут в состоянии активно, но по факту движений по ним не будет. А в предложенной обработке используется механизм, в котором задействованы как минимум три задания: на оркестрацию, на паузу и на обработку данных. Можно, конечно, вернуть оркестрацию в основной поток, паузу переделать без фоновых заданий, но даже тогда многопоточность будет лишь симулятивная, поскольку задания запустятся, но будут ждать выполнения первого и так далее. Сейчас же для файловой базы запуск многопоточной обработки отключен, но посмотреть код и запустить сбор данных и параметров можно.
Также хочется отметить, что фоновые задания не используют лицензию на запуск клиента, поэтому не стоит переживать из-за них (проверял лично, однажды по ошибке запустил более 30 тысяч заданий, на лицензии разработчика)
Ну и напоследок, почему все таки расширение, а не обработка. Дело в том, что запуск методов обработки в фоновом задании невозможен без модификации основной базы. В то же время, выполнение кода с параметрами в принципе доступно из БСП, но только в безопасном режиме. В очень безопасном режиме. В настолько безопасном, что все, что фрагмент кода выполнил, в конце отменяется. А фоновое задание может вызывать только метод, не может просто фрагмент кода выполнить, так что то, что есть - не подходит.
И это хорошо, что консоль кода будет стабильно доступна только пользователям с полными правами. Для остальных назначенная роль почему-то слетает - я так понимаю, это проверки БСП, не знаю, как их обойти, видимо отдельный профиль группы доступа нужен. Так что тоже в каком-то смысле безопасно) К тому же непосредственно фоновая обработка данных выполняется таки в безопасном режиме, кто не согласен - you are welcome in модуль менеджера.
Код консоли совместим с версией 8.3.23 (режим совместимости расширения), однако по некоторым сведениям, JS в поле HTML может работать не так, как ожидалось, в версиях до 8.3.25, имейте ввиду - хотя я ничего странного не заметил.
P.S. Функции, которые появились в этой версии консоли:
1. многопоточное выполнение кода со следующими особенностями:
а) фоновый запуск потоков обработки данных
б) отслеживание прогресса через панель состояния
в) отмена в любой момент (невыполненной части)
2. сохранение временных копий файла при запуске на исполнение (сохраняются только различные версии)
3. два окна для кодирования (при включенном режиме многопоточности) - глюков быть не должно, вроде аккуратно делал, но правок было очень много, все кнопки не проверял. Если что - обращайтесь, буду рад исправить.
Проверено на следующих конфигурациях и релизах:
- Бухгалтерия предприятия, редакция 3.0, релизы 3.0.192.25
Вступайте в нашу телеграмм-группу Инфостарт