Каталог решений - Многопоточность. Универсальный «Менеджер потоков» (фреймворк) с отслеживанием зависимости объектов

Многопоточность. Универсальный «Менеджер потоков» (фреймворк) с отслеживанием зависимости объектов

Многопоточность. Универсальный «Менеджер потоков» (фреймворк) с отслеживанием зависимости объектов

В наличии

Восстановление партий, расчет зарплаты, пакетное формирование документов или отчетов — теперь все это стало доступнее.
* Есть желание повысить скорость работы медленных алгоритмов! Но…
* Нет времени думать о реализации многопоточности?
* о запуске и остановке потоков?
* о поддержании потоков в рабочем состоянии?
* о передаче данных в потоки и как получить ответ из потока?
* об организации последовательности?
Тогда ЭТО — то что надо!!!

Категория:

Описание

Обновление для всех!

Еще больше возможностей, еще быстрее обработка, еще проще разработка — Универсальный менеджер потоков 2.0. 

Полная версия, полностью открытый код и только за $m.

Данный материал переходит в разряд статьи

Очень кратко, о чем речь…

Фреймворк в виде одного общего модуля, позволяющего при получении объектов на обработку запускать их в несколько потоков. Особенности:

  • Нет необходимости рассчитывать «порции» для обработки;
  • Нет необходимости организовывать файловый обмен между потоками;
  • Возможность запускать несколько менеджеров потоков одновременно, при этом потоки одного менеджера, могут запускать новые менеджеры со своими задачами и потоками (главное чтоб лицензий хватило :));
  • Можно выстраивать граф зависимости объектов, что позволяет, например, избегать взаимоблокировок и/или организовать восстановление партий (на нашем предприятии удалось добиться 10х+ ускорения при 10 потоках в рабочее время – 200+ активных пользователей — Результаты работы механизма);
  • Можно и нужно производить вмешательство в алгоритмы с помощью событий;
  • Возможность описывать алгоритмы событий, как в модуле менеджера, так и в любом другом модуле БД (предпочтительно), а также во внешней обработке.
  • Автоматический рестарт потока в случае ошибок;
  • Контроль за количеством рестартов по каждому объекту;
  • Возможность получать «ответы» от потоков;
  • Возможность контролировать работу с помощью «Инструментов разработчика» или иных отчетов;
  • Возможность срочного прерывания работы;
  • И многое другое…

О том, как оно все работает описано ниже, при желании можно и свое написать 🙂

Буков очень много, но и картинок достаточно 🙂

Оглавление

Введение

Результаты работы механизма

Как проводились тесты

Железо

Сервер 1С и Клиент

SQL Сервер

Программное обеспечение

Сервер 1С и Клиент

SQL Сервер

Предыстория

Общая схема

Запуск и остановка ФЗ

Передача данных между ФЗ

Расчет «Ресурса»

Примеры формирования ресурсов

Пример 1 (По складам — для восстановления партий не подходит)

Пример 2 (По складам — для восстановления партий подходит)

Пример 3 (По складам и номенклатуре — для восстановления партий не подходит)

Пример 4 (По складам и номенклатуре — для восстановления партий не подходит)

Пример 5 (По складам и номенклатуре — для восстановления партий подходит)

Пример 6 (Варианты на одном примере)

Очереди

Очередь для менеджера

Очередь для потоков

Обновление «Очереди для потоков»

Запуск документов в поток

Обработка ошибок

Функция ПолучитьСтруктуруПараметровИнициализацииМенеджераПотоков()

Функция ИнициализироватьМенеджерПотоков()

Процедура «ОбработатьОбъект()»

Функция «ОбработатьСобытиеРазработчика()»

Месторасположение функции «ОбработатьСобытиеРазработчика()»

В общем модуле «МенеджераПотоков»

В произвольном модуле БД (рекомендуемый)

Во внешней обработке

События функции «ОбработатьСобытиеРазработчика()»

Событие: «ПередЗапускомМенеджераПотоков»

Событие: «ПриЗапускеМенеджераПотоков»

Событие: «ПриПолученииМассиваРесурсов»

Событие: «ПриОбработкеИсключенийИзОчередиМенеджера»

Событие: «ПриОпределенииТипДанныхВПотоке»

Событие: «ПриОбработкеДействияПотока»

Событие: «ПриОбработкеОтветаПотока»

Событие: «ПриНевозможностиОбработатьОбъект»

Событие: «ПередЗавершениемМенеджераПотоков»

Событие: «ПослеЗавершенияМенеджераПотоков»

Событие: «ПриПолученииМестаХраненияФайловМониторинга»

Вариант передачи данных между событиями

Отчеты

Демо обработки

Менеджер потоков (Демо)

Заключение

Обновления

Введение

В данной публикации будет максимально подробно «разжеван» способ реализации «Менеджера потоков», а так же предоставлены демо обработки с готовым открытым исходным кодом.

Описание и примеры с кодом, в данной статье, будут даны в общих чертах по принципу от общего к частному. На каких-то скринах будут отсутствовать параметры процедур и функций или строки кода, в связи с тем, что в данной конкретной теме это не является существенным.

Все повествование будет вестись на примере «Восстановления партий», т.к. эта задача была первоочередной, но в дальнейшем переродилась в «Универсальный механизм». «Универсальным» он назван по той причине, что общий модуль, где располагаются алгоритмы «Менеджера потоков» могут быть обособлены и не изменны на  всем протяжении использования механизма, но при этом решать разные задачи (восстановление партий, расчет зарплаты, формирование пакетов документов, формирование отчетов и т.д.).

Весь код и в скринах, и в обработках написан на обычных формах, т.к. разработка велась на базе УПП. Описание предоставлено в рамках «Восстановления партий».

Но обо всем по порядку …

Вверх

Результаты работы механизма

При распараллеливании на 10 потоков.

ПоказательНоябрь 2016Декабрь 2016Январь 2017Февраль 2017
Документов в последовательности (шт.)22865182981478817189
Документов для восстановления (шт.)14192925285379921
Однопоточное восстановление («холодный»/«прогретый») (мин.)293/265215/196172/162219/203
Параллельное восстановление («холодный»/«прогретый») (мин.)30/2420/1616/1419/17

Здесь и далее под «холодный» и «прогреты» понимается запуск обработки сразу после восстановления БД («холодный») и запуск повторно («прогретый»).

Вверх

Как проводились тесты:

  • на копии продуктивной БД (УПП; 3 года; ~200 Гб; 1 организация);
  • по 4 месяцам (ноябрь 2016, декабрь 2016, январь 2017, февраль 2017);
  • копия БД восстанавливалась на момент перед первым восстановлением последовательности за период;
  • по каждому месяцу было развёрнуто по 2 копии БД, в одной запускался типовое восстановление (без настроек обработки), в другой с использованием «Менеджера потоков»

Вверх

Железо

Сервер 1С и Клиент

  • Процессор: i7-3930K 3.2 ГГц;
  • ОЗУ: 16Гб;
  • ПЗУ: SSD KINGSTON SH103S3120G;

Вверх

SQL Сервер

(продуктив: 1 продуктивная база; 15-18 баз разработчиков)

  • Процессор: 2xXeon E5-2697v2 2.7 ГГц;
  • ОЗУ: 128Гб;
  • ПЗУ Система: RAID-1 2xSSD IBM System X 512Гб;
  • ПЗУ База: SSD Intel P3700 800Гб (только приобрели – тестируем, обе тестируемые базы тут);
  • ПЗУ Tempdb: RAID-10 4xSSD IBM System X 512Гб.

Вверх

Программное обеспечение

Сервер 1С и Клиент

  • Win 7 Prof SP1 64x
  • 1С:Предприятие 8.3 (8.3.9.1850) 32x

Вверх

SQL Сервер

  • WinServer 2012 R2 Standard 64x
  • SQL Server 2008 R2 (10.50.6000)

Вверх

Предыстория

(кому не интересно могут смело идти дальше)

Мое основное рабочее место в крупной строительной организации. Часто бывает, что ближе к концу отчетному периоду начинают все интенсивнее приходить документы, включая те, что относятся к началу отчетного периода. И приходиться заново проводить восстановление партий и перезакрывать период. Все бы ни чего, но делать это в рабочее время не получается из-за блокировок. Приходится восстановление проводить по ночам, а период закрывать на следующий день и так по каждому месяцу до крайнего. В худшем случае может потребоваться 3 дня L.

Если месяц закрыт и все ошибки выверены, то на полное перезакрытие уходит около 5 часов, 3-4 из которых – это восстановление партий.  В свою очередь восстановление партий — это всего лишь один этап при закрытии месяца, а всего их от 28 до 31 в зависимости от периода. При вопросе, что оптимизировать сомнений уже не осталось.

Я был знаком с механизмом фоновых заданий, но часто на практике его использовать не приходилось. Мне виделось решение проблемы именно тут, но как?

У нашей организации очень обширная география (от Сочи до Камчатки). В своем большинстве объекты обособленные. Склады и производство находятся в непосредственной близости друг к другу. Перемещения материалов между объектами происходят достаточно редко по сравнению поступлениями и списаниями на них. Тогда и появилась первая мысль «а нельзя ли восстанавливать последовательность в рамках объектов?».

Первая версия обработки в данном направлении была готова примерно через 2 недели (это был февраль 2016г.) и тогда показала неплохие результаты, партии восстанавливались примерно за 50 мин. Но у данной обработки были большие минусы:

  • была не пригодна для общего использования (не у всех такая особенность учета складов и производства);
  • достаточно много корректировок в типовом коде;
  • достаточно сложна для понимания принципов работы при вычислении порции для потоков.

Как в жизни, если не получается или получается «не совсем удачно» — обратимся к мануалу :).

Хотелось большего выигрыша в скорости, что подвигло меня посмотреть, что по этому поводу пишут в интернете. Нашел интересные статьи:

  • Ускорение восстановления последовательности документов в УПП. (Источник: http://www.forum.mista.ru/topic.php?id=541251&page=1); Это был первый источник, где можно было ознакомиться с мыслями сообщества по данному вопросу. Вы этой теме была найдена ссылка – след. пункт, на более глубокий теоретический подход к решению проблемы.
  • Ускорение процесса восстановления последовательности в 1С 8 УПП с использованием параллельных вычислений (Источник: http://www.softpoint.ru/archive/article_id375.php); Достаточно подробно и в картинках – весьма познавательно.
  • Параллельное восстановление партий (Источник: http://techlab.rarus.ru/news/articles/parallelnoe-vosstanovlenie-partiy/ ) Тут больше о достижении 1С-Рарус в решении данного вопроса, а также представлены результаты одного из заказчиков.

Это дало мне надежду, что можно найти еще более оптимальное решение. Но в связи с загрузкой на работе пришлось закинуть идею в дальний ящик, т.к. задачу решал на энтузиазме, а не по просьбе заказчика.

…

Снова вернуться к данной разработке меня подвигло появление свободного времени и любопытство. Еще раз ознакомившись с вышеописанными источниками решил поискать, о какой доработке типового УПП писал «1С-Рарус». Решил поискать «тормоза» типового решения. Кандидаты нашлись довольно быстро — это:

  • Настройка в обработке «Восстановление партий» Меню – «Настройка» — «Настройка обработки» — «Ручная настройка» — «Количество документов в выборке». Данный параметр отвечает за количество итераций «Запрос в цикле». По умолчанию = 1, т.е. выполнение запроса на выборку 1 документа и так столько раз, сколько документов в обрабатываемом периоде последовательности.
  • Процедура «СдвинутьПоследовательностьВперед()» в общем модуле «Заполнение документов» из которой вызывается функция «ОпределитьНеобходимостьСдвигаГраницы», что приводит нас, как и в первом случае к «Запросу в цикле».
  • Не оптимально написанные запросы в общем модуле «УправлениеЗапасамиПартионныйУчет»:
    • Процедура ЗаполнитьЗапросПартийНаСкладахУпр;
    • Процедура ЗаполнитьЗапросПартийНаСкладахБух;
    • Процедура ЗаполнитьЗапросПартийНаСкладахНал;

Последнее, скорее всего и есть тот самый «патч» :).

Все остальное было не столь существенно:

После изменения настроек и исправления запросов результат стал следующий:

ПоказательНоябрь 2016Декабрь 2016Январь 2017Февраль 2017
Однопоточное восстановление («холодный»/«прогретый») (мин.)293/265215/196172/162219/203
Однопоточное восстановление + оптимизация («холодный»/«прогретый» ) (мин.)130/10885/6767/5476/62
Параллельное восстановление («холодный»/«прогретый») (мин.)30/2420/1616/1419/17

Это уже позволяло в критической ситуации (1 сессия в БД с блокировкой доступа) провести восстановление квартала за 1 рабочий день.

Далее, было желание реализации фоновых заданий. Решил попробовать схему описанную «SoftPoint», т.к. она более детально и подробно описана, но при было желание избавиться от минусов прошлой разработки.

На удивление решение оказалось значительно проще прошлогодних алгоритмов, за исключением одного момента, а именно управления документами в очередях. Так же мне «не давала покоя» реализация по принципу «у каждого потока своя очередь». В итоге я приступил к новой разработке, результатами которой и решил поделиться со всеми. И так поехали…

Вверх

Общая схема

Данная схема показано очень упрощенно, дабы не испугать не искушенного. Как видно на рисунке необходимо изменить однопоточное проведение в цикле, на проведение в несколько потоков.

В общем случае потребуется внести 3 корректировки в типовой код:

  • Перед циклом запустить инициализацию менеджера потоков;
  • В цикле переопределить процедуру выполнения;
  • После цикла дождаться завершения работы менеджера.

Общие описание каждой из процедур основного кода:

  • Функция ИнициализироватьМенеджерПотоков() — предназначена для инициализации работы в потоках и установки начальных параметров менеджера потоков;
  • Процедура ОбработатьОбъект() — производит первичные расчеты по объекту и передает его при необходимости в менеджер потоков;
  • Процедура ДождатьсяОстановкиМенеджераПотоков() — ожидает завершения работы всех фоновых заданий, а так же производит сохранение всех отчетов мониторинга.

Общие описание основных процедур фонового задания «Менеджер потоков»:

  • Функция ОбновитьОчередьОбъектов() – очищает "Очередь для потоков" от объектов если они уже обработаны, при необходимости перезапускает потоки, также определяет какие потоки свободны;
  • Процедура ЗапуститьОбъектыИзОчередиВПоток () — производит передачу объектов из «Очереди для потоков» в свободные потоки;
  • Процедура ДобавитьОбъектВОчередь() — добавляет объект в "Очередь для потоков" если есть свободное место;

Вверх

Запуск и остановка ФЗ

Контроль запуска и остановки фоновых заданий очень важен, т.к. напрямую на них влиять «не удобно». Для исключительных ситуаций, например, не правильно выставлены начальные настройки, предоставлена простая обработка — «Интерактивная остановка менеджеров потоков». Ну или просто можно вызвать процедуру «МенеджерПотоков. ОстановитьМенеджерПотоковИнтерактивно()»

На данном рисунке видно, что все фоновые задания запускаются из процедуры «ИнициализироватьМенеджерПотоков». Сначала запускается менеджер потоков, а уже он запускает фоновые задания потоков. В каждом фоновом задании, включая «Менеджер потоков» запускается «бесконечный цикл». На каждой итерации цикла, потоки отслеживают активность «Менеджера потоков» и если он не активен, они завершают свою работу. В то же время, цикл основной программы, так же на каждой итерации проверяет активность «Менеджера потоков» и в случае его преждевременного завершения вызывает ошибку в основной программе.

После того, как цикл основной программы был завершен, осуществляется установка переменной «ОбъектыЗакончились» в значение «Истина», затем запускается «бесконечный цикл» с ожиданием остановки «Менеджера потоков».

«Менеджер потоков» на каждой итерации своего «Бесконечного цикла» анализирует 3 параметра:

  • ОбъектыЗакончились – значение переменной переданной из основной программы со значением «Истина» сообщает о том, что новых объектов в «Менеджер потоков» не поступит;
  • КоличествоОбъектовВОчереди – говорит само за себя, количество объектов в «Очереди для потоков»;
  • КоличествоЗанятыхПотоков – так же говорит само за себя;

Как только выполняется «условие выхода» из «Бесконечного цикла» — «Менеджер потоков» завершает свою работу.

Основная программа «увидев» не активность «Менеджера потоков» выходит из «бесконечного цикла».

Вверх

Передача данных между ФЗ

Это был один из самых важных вопросов в решении данной обработки, т.к. хотелось реализовать возможность доработки с минимальным вмешательством в типовой код и в структуру метаданных, без создания таблиц временного хранения данных.

«Хранилище общих настроек» подошло как нельзя кстати. Оно обладает как минимум 2ми плюсами:

  • Хранит данные в разрезе пользователей ИБ;
  • Хранит «Произвольный» тип данных.

Наблюдать «в живую», как происходит передача данным между фоновыми заданиями можно с помощью «Инструментов разработчика» — //sale.itcity.ru/public/15126/ или http://devtool1c.ucoz.ru/ . Обработка «Редактор хранилищ настроек (ИР)» — Закладка «Общие».

 «Общение» происходит по принципу «семафоров». В одном коде алгоритм на каждой итерации цикла проверяет значение (чтение – пунктирная стрелка) из «ХранилищаОбщихНастроек» на равенство «Неопределено» и при необходимости записывает (запись – прямая стрелка) туда же необходимое значение, а в другом коде (фоновом задании), наоборот проверяет значение из «ХранилищаОбщихНастроек» на НЕ равенство «Неопределено» и при необходимости записывает «Неопределено». Чуть сложнее ситуация обстоит с «ЗначениеДляПотока», о чем будет рассказано дальше, но принцип точно такой же.

По такому же принципу реализована передача значения переменной «ДокументыЗакончились» (зеленые стрелки) рассмотренной в разделе «Запуск и остановка ФЗ».

Вверх

Расчет «Ресурса»

Ресурсом названа уникальная комбинация одного или нескольких значений объекта. Какая это будет комбинация(и), разработчик определяет сам. Объекты с одинаковым(и) ресурсами "строят" граф зависимости объектов, а так же производится объединение графов, если их больше одного. На представленном рисунке засчитываются ресурсы для двух графов, которые сразу объединяются в один:

  • Склад и Номенклатура
  • Заказ

(В нашей рабочей базе УПП строиться 3 графа для корректного расчета партий)

В процедуре «ИнициализацииМенеджераПотоков()» происходит создание «Общего», в рамках текущего выполнения, «Соответствия» всех ресурсов. В процессе обработки каждого документа создается «МассивЗначенийРесурсов», значениями которого является массив конкретного ресурса «МассивРесурса». По каждому «МассивРесурса» формируется составная строка из уникальных идентификаторов ссылок, которые, в свою очередь являются ключами в «СоответствияРесурсов» созданном при инициализации. Если ключ не найден, то в «СоответствиеРесурсов» заносится новое значение – Новый УникальныйИдентификатор().

Примеры формирования ресурсов:

Пример1:

Для восстановления партий не подойдет, т.к. по документу "Док6" — не корректно составлен ресурс, что влечет за собой, проведение "Док6" одновременно с "Док1". Ресурс "Док6" не совпадает ни с одним другим ресурсом других документов.

Вверх

Пример 2

Для восстановления партий подойдет, т.к. ресурсы по документу "Док6" совпадают с ресурсом "Док4" и "Док5", следовательно "Док6" пойдет в обработку, толькот после того, как обработаются "Док4" и "Док5"

Вверх

Пример 3

Для восстановления партий не подойдет, т.к. по всем документам получены разные ресурсы и документы идут в обработку независимо друг от друга

Вверх

Пример 4

Для восстановления партий не подойдет, т.к. получены слишком "раздробленные" ресурсы — все документы, кроме "Док1" и "Док2", чем-то зависят от других документов.

Вверх

Пример 5

Для восстановления партий подойдет, т.к. получены достаточные ресурсы, для того распараллелить и "обойти" блокировки.

Вверх

Пример 6

Краткий пример с двумя "почти" одинаковыми документами, но с разными результатами.

ВАЖНО!!! Последовательность значений в массиве "МассивРесурса" ИМЕЕТ значение.

Вверх

Очереди

При реализации данной обработки пришлось создавать несколько очередей. Одна на стыке «Код основной программы» и «Менеджер потоков» — «ОчередьДляМенеджера», друга на стыке «Менеджер потоков» и «Фоновые задания» — «ОчередьДляПотоков».

Очередь для менеджера

Данная очередь вообще появилась под конец разработки, при анализе графиков наполнения «Очереди для потоков».

В последовательности присутствуют разные документы, как те по которым необходимо восстанавливать последовательность («Требование накладная», «Внутреннее перемещение», и т.д.), так и те по которым этого делать не надо («Поступление товаров и услуг»). Выяснилось, что возникали ситуация (длинная серия из документов, требующих восстановления последовательсти), когда «Очередь для потоков» была забита под завязку (она ограниченного размер, об этом чуть позже) и «Менеджер потоков» не мог принять новый документ от «основной программы». В этот момент «Основная программа» запускала «Бесконечный цикл» в ожидании, когда «Менеджер потоков» будет готов забрать документ. С другой стороны, были и обратные ситуации (длинная серия из документов НЕ требующих восстановления), в этот момент из основной программы не передавались документы в «Менеджер потоков» и данный этап мог быть достаточно длительным, чтобы полностью очистилась «Очередь для потоков» и опять возникал простой в ожидании появления документов для проведения.

Данная очередь и является своего рода буфером, наполняясь при первой ситуации и постепенно очищаясь при возникновении второй.

В процедуре «ИнициализацииМенеджераПотоков()» происходит создание бесконечного массива «МассивОчередьМенеджера». При выполнении обработки документов определяется необходимость восстановления партий по текущему документу. Если документ требует обработки, то он добавляется в очередь. Далее проверяется готов ли «Менеджер потоков» принять новый документ. Если «Готов», то из очереди передается первое значение в «Менеджер потоков» и затем оно удаляется из очереди. После того как цикл обработки документов «Основной программы» отработает, вызывается процедура «ДождатьсяОстановкиМенеджераПотоков». В самом начале которой идет обход «Очереди для менеджера» и постепенно до передаются документы в «Менеджер потоков» с ожиданием если «Менеджер потоков» в какой-то момент не готов принять документ.

Вверх

Очередь для потоков

Данная очередь является основной для потоков, по большому счету — это граф. Данная очередь является ограниченной по размеру в отличии от «Очередь для менеджера». Связано это с ее постоянными обновлениями. В данном примере ее размер в 3 раза превышает количество потоков. Если ее сделать очень большой, это негативно скажется на общем результате, т.к. параллельности может и не добавит (смотри раздел «Запуск документов из очереди в поток»), а «расходы» на ее поддержание будут значительными.

В самом начале запуска фонового задания «Менеджера потоков» определяется максимальная глубина очереди. Данное значение является предельным для добавления нового документа в очередь. В процессе работы «Менеджера потоков» вызывается процедура «ДобавитьОбъектВОчередь», которая проверяет появилось ли свободное место в очереди, рассчитывает зависимость документов на текущий момент и добавляет документ в очередь (граф).

Вверх

Обновление «Очереди для потоков»

В обязанности данной функции входит ряд проверок и действий, а именно:

  • Определение свободных потоков;
  • Перезапуск потоков в случае ошибок;
  • Очистка «Очереди для потоков» от отработанных документов и от зависимости к этим документам;
  • Получение «отчета» от фонового задания о том, как прошла обработка документа (был ли отказ) – см. раздел «Обработка ошибок».

Вверх

Запуск документов в поток

Суть данной процедуры достаточно проста. Она производит передачу независимых документов в свободные потоки.

На каждой итерации цикла проверяется если ли свободные потоки и «независимые» документы в графе. Каждый «независимый» документ направляется в отдельный поток. Если количество «независимых» документов превышает количество свободных потоков, то они ждут распределения в следующих итерациях.

На первой итерации видно, что независимых документов в нашем графе – 3 шт. Каждый из них направляется в свой поток.

На второй итерации один из ранее проведенных документов (Док3) был проведен. От него уже освобождены (функцией ОбновитьОчередьОбъектов()) зависимые документы (Док4, Док7, Док9). Документ «Док9» стал «независимым» и он направляется в свободный поток.

На третьей итерации все повторяется, провелся «Док1». Освобождаются от зависимости четыре документа (Док2, Док4, Док5, Док7), три из которых становятся «Независимыми» и отправляются в потоки.

Вверх

Обработка ошибок

Upd: Данный механизм претерпел значительные изменения  — Универсальный менеджер потоков 2.0

При отработке фоновых заданий хорошо бы знать, какие документы отработали, а по каким прошел «Отказ».

Все начинается с кода основной программы, где в функции «ИнициализироватьМенеджерПотоков()» получается адрес «АдресВХОшибок» временного хранилища, куда необходимо вернуть информацию по ошибкам. Данный адрес отправляется в «Менеджер потоков». В «Менеджере потоков» на каждой итерации цикла в «Очередь для потоков» по возможности добавляется информация (Структура). Поток, получив данную структуру обрабатывает документ и в это же значение «ЗначениеДляПотока» записывает результат выполнения (Булево). На одной из следующих итерация «Менеджер потоков» считывает значение «ЗначенияДляПотоков» в процедуре «ОбновитьОчередьОбъектов» и определяет тип и значение переменной. Если там:

  • «Неопределено» — значит поток свободен;
  • «Булево» — «Да» — обработка документа завершена успешно. Перезаписываем значение в «Неопределено». Поток свободен;
  • «Булево» — «Нет» — обработка документа завершена с ошибкой. Перезаписываем значение в «Неопределено», сохраняем ссылку и сообщения пользователю в таблицу для дальнейшей передачи в код «основной программы». Поток свободен;
  • «Струкутра» — поток еще занят.

После того, как в «Менеджере потоков» выполняется условие завершения работы. Список ошибок сохраняется во временном хранилище по адресу «АдресВХОшибок». На основании ошибочных документов определяется на какой момент времени сдвинуть границу последовательности.

Если ошибок нет – граница устанавливается на последний документ последовательности.

Если есть ошибки, рассчитывается минимальный момент времени среди ошибочных документов, в последовательностях (Упр. и Бух.) находиться предыдущие ему документы и для каждой последовательности устанавливается своя граница.

Вверх

Функция ПолучитьСтруктуруПараметровИнициализацииМенеджераПотоков()

Данная функция получает структуру параметров необходимых при инициализации "МенеджераПотоков".

  • Параметры функции:
    • РазрезМенеджеров (Тип: Строка) – произвольный идентификатор текущего экземпляра менеджера потоков. Отвечает за разделение данных и ветвление алгоритмов описанных разработчиком (см. раздел «Функция ОбработатьСобытиеРазработчика») между несколькими одновременно запущенными Менеджерами потоков.
  • Возвращаемое значение: – Тип: Структура
    • РазрезМенеджеров (<РазрезМенеджеров>) — передаваемый параметр;
    • КоличествоПотоков (Тип: Число) – отвечает за количество запущенных потоков для обработки информации (по умолчанию: 10);
    • МодульОбработкиСобытийРазработчика (Тип: Неопределено / Строка / ДвоичныеДанные) – определяет, где располагаются алгоритмы разработчика (см. раздел «Функция ОбработатьСобытиеРазработчика»)
      • Неопределено – в общем модуле «МенеджерПотоков»;
      • Строка «ПутьДоМодуля.ИмяФункции» — в произвольном модуле БД;
      • ДвоичныеДанные — в модуле объекта произвольной внешней обработки (по умолчанию: Неопределено). Двоичные данные сформированы на основании месторасположения текущей обработки (см. Демо обработки — перезапись элементов справочников);
    • СтруктураПараметрыМенеджера (Тип: Структура) – Структура с параметрами для передачи их из основной программы в менеджер потоков. Если не определять, будет сформирована базовая структура параметров (по умолчанию: Неопределено);
    • ВестиМониторингОчередиМенеджера (Тип: Булево) – Флаг отвечает за запись данных о наполнении менеджера потоков (по умолчанию: Ложь) (См. раздел «Отчеты»);
    • ВестиМониторингПотоков (Тип: Булево) – Флаг отвечает за запись данных о работе потоков (по умолчанию: Ложь) (См. раздел «Отчеты»);
    • ВестиМониторингПорядкаОбработки (Тип: Булево) – Флаг отвечает за запись данных о порядке обработки объектов (по умолчанию: Ложь)(См. раздел «Отчеты»);
    • ПределКоличествоПопытокОбработатьОбъект (Тип: Число) — Количество попыток обработать объект. По достижению предела объект будет пропущен (по умолчанию: 5). Не доступно в демо-режиме;
    • КоэффициентКратностиОчередиПотоковКПотокам (Тип: Число) — Коэффициент влияющий на размер "Очереди потоков" (по умолчанию: 3). Не доступно в демо-режиме.

Вверх

Функция ИнициализироватьМенеджерПотоков()

Данная функция является основной, при настройке менеджера потоков, предназначена для инициализации работы в потоках и установки начальных параметров менеджера потоков.

Вызов данной функции осуществляется в начале работы. Примерная схема работы функции:

Вверх

Процедура «ОбработатьОбъект()»

Upd: По мимо данной процедуры, появились НОВЫЕ — Универсальный менеджер потоков 2.0

Данная процедура является «подменной» первоначального однопоточного выполнения.

Параметры функции:

  • «СтруктураПараметрыМенеджера» (Тип: Структура) – Структура полученная после вызова функции «ИнициализироватьМенеджерПотоков» — см. раздел «Функция ИнициализироватьМенеджерПотоков»;
  • «ОбрабатываемыйОбъект» (Тип: Произвольный) – Ссылка на обрабатываемый объект
  • «ЗначениеДляМенеджера» (Тип: Структура) – Произвольный набор параметров передаваемый в менеджер потоков.

«ОбрабатываемыйОбъект» автоматически включается в структуру «ЗначениеДляМенеджера».

Вверх

Функция «ОбработатьСобытиеРазработчика()»

Upd: Данный раздел претерпел значительные изменения  — Универсальный менеджер потоков 2.0

В принципе это единственная функция, куда разработчику необходимо вносить свой код. Вызов данной функции по умолчанию настроен из разных мест и позволяет в достаточной степени влиять на алгоритм.

Из какого места, какое событие вызывается показано на следующем рисунке.

У данной функции всего 1 параметр и одно значение возврата:

  • ПараметрыСобытия – Структура параметров необходимая событиям, у каждого события свой состав, но при этом 3 параметра обязательные:
    • РазрезМенеджеров — текстовая переменная, (см. "РазрезМенеджеров").
    • ИмяСобытия – текстовая переменная, по умолчанию может принимать одно из следующих значений:
      • «ПередЗапускомМенеджераПотоков»;
      • «ПриЗапускеМенеджераПотоков»;
      • «ПриПолученииМассиваРесурсов» как функция;
      • «ПриОбработкеИсключенийИзОчередиМенеджера»;
      • «ПриОпределенииТипДанныхВПотоке» как функция;
      • «ПриОбработкеДействияПотока» как функция;
      • «ПриОбработкеОтветаПотока»;
      • «ПриНевозможностиОбработатьОбъект»;
      • «ПередЗавершениемМенеджераПотоков»;
      • «ПослеЗавершенияМенеджераПотоков»;
      • «ПриПолученииМестаХраненияФайловМониторинга» как функция.
    • СтруктураМодуляОбработкиСобытийРазработчика – Структура хранящая информацию о том, где находятся алгоритмы разработчика
  • События выступающие в роли функции могут вернуть определенные результаты в переменную «ОтветСобытия»:
    • «ПриПолученииМассиваРесурсов» — типы: Массив (См. раздел «Расчет ресурса») / Неопределено (по умолчанию));
    • «ПриОпределенииТипДанныхВПотоке» — Тип: Строка
      • «ДанныеДляПотока»;
      • «ОтветПотока»;
      • «Неопределено» (по умолчанию);
    • «ПриОбработкеДействияПотока» — Произвольный (по умолчанию — Неопределено);
    • «ПриПолученииМестаХраненияФайловМониторинга» — Строка  / Неопределено (по умолчанию).

Вверх

Месторасположение функции «ОбработатьСобытиеРазработчика()»

Данная функция, состоит из 2х частей:

  • Базовой (находится в общем модуле «МенеджерПотоков»);
  • Вспомогательная (может находиться в произвольном модуле или во внешней обработке).

Вверх

В общем модуле «МенеджераПотоков»

Тут все, как обычно, находим данную функцию и начинаем вставлять свои алгоритмы.

Плюсы:

  • Весь алгоритм распараллеливания находиться в одном модуле (на самом деле сомнительный плюс J);
  • Можно проследить ход выполнения отладчиком;

Минусы:

  • При обновлении (если будут выпускаться новые редакции «Универсального менеджера потоков» — зависит заинтересованности сообщества и реализации новых идей), придется не просто заменить модуль, но еще и перенести свои алгоритмы.

Вверх

В произвольном модуле БД (рекомендуемый)

В данном случае мы описываем экспортную функцию в произвольном модуле, который можем вызвать из отчета или обработки («Общий модуль» / «Модуль объекта» / …);

Изначально будет сделан вызов «базовой части» — функции «ОбработатьСобытиеРазработчика()» из общего модуля «МенеджерПотоков», а затем перенаправлен в необходимый произвольный модуль. Куда будут перенаправляется вызовы определятся при инициализации менеджера потоков.

Плюсы:

  • Простой способ обновления (если будут обновления) «Универсального менеджера потоков»
  • Модулей может быть неограниченное количество;
  • Можно проследить ход выполнения отладчиком;

Минусы:

  • Изменение метаданных;

Вверх

Во внешней обработке

Данный способ подойдет для написания внешних обработок, т.к. позволяет описать алгоритм ТОЛЬКО в модуле обработки без корректировок БД.

ВНИМАНИЕ!!! По умолчанию создание обработки происходит в «безопасном режиме», что накладывает ряд ограничений.

  • привилегированный режим отменяется, если он был установлен;
  • попытки перехода в привилегированный режим игнорируются;
  • запрещены операции с COM-объектами;
  • запрещена загрузка и подключение внешних компонентов;
  • запрещен доступ к файловой системе (кроме временных файлов);
  • запрещен доступ к Интернету.

Изменение данного параметра устанавливается в

«Функция ПолучитьСтруктуруМодуляОбработчикаСобытийРазработчика(РазрезМенеджеров)»

Строка:

ОбъектМодуль = ВнешниеОбработки.Создать(ИмяТемпФайла, Ложь / Истина);

Истина – Безопасный режим;

Ложь – НЕ безопасный режим.

По причине того, что в демо обработке необходимо сохранять файл(ы) – "безопасный режим" необходимо отключить в модуле «МенеджерПотоков».

Плюсы:

  • Простой способ обновления (если будут обновления) «Универсального менеджера потоков»
  • Не требует изменение метаданных (если уже есть общий модуль «МенеджерПотоков»);

Минусы:

  • Невозможно пройти отладчиком события разработчика 🙁

Вверх

События функции «ОбработатьСобытиеРазработчика()»

Все параметры, передаваемые в данную функцию передаются через структуру «ПараметрыСобытия». Параметры по умолчанию:

  • «РазрезМенеджеров» — см. раздел «функция ИнициализироватьМенеджерПотоков()»
  • «ИмяСобытия» — строка и предопределенным именем события:
    • «ПередЗапускомМенеджераПотоков»;
    • «ПриЗапускеМенеджераПотоков»;
    • «ПриПолученииМассиваРесурсов»;
    • «ПриОбработкеИсключенийИзОчередиМенеджера»;
    • «ПриОпределенииТипДанныхВПотоке»;
    • «ПриОбработкеДействияПотока»;
    • «ПриОбработкеОтветаПотока»;
    • «ПриНевозможностиОбработатьОбъект»
    • «ПередЗавершениемМенеджераПотоков»;
    • «ПослеЗавершенияМенеджераПотоков»;
    • «ПриПолученииМестаХраненияФайловМониторинга».
  • «СтруктураМодуляОбработкиСобытийРазработчика» — служебная структура для определения вызова событий разработчика;

Вверх

Событие: «ПередЗапускомМенеджераПотоков»

Место вызова: Код основной программы;

Принцип работы: Как процедура;

Доступные параметры:

  • «СтруктураПараметрыМенеджера»
    • Служебные параметры (РазрезМенеджеров, СтруктураМодуляОбработкиСобытийРазработчика, ВестиМониторингПотоков, ВестиМониторингПорядкаОбработки, АдресВХМониторингПотоков, АдресВХМониторингПорядкаОбработки)
    • Дополнительные произвольные параметры переданные в функцию ИнициализироватьМенеджерПотоков() в параметр «СтруктураПараметрыМенеджера» (см. раздел «функция ИнициализироватьМенеджерПотоков()»)

Назначение: Позволяет передавать произвольные данные из основной программы в «Менеджер потоков»

Назначение в рамках восстановления партий: Определяет адрес во временном хранилище, куда вернуть таблицу значений с ошибками при восстановлении партий.

Вверх

Событие: «ПриЗапускеМенеджераПотоков»

Место вызова: Фоновое задание «МенеджерПотоков»;

Принцип работы: Как процедура;

Доступные параметры:

  • «СтруктураПараметрыМенеджера» — см. событие «ПередЗапускомМенеджераПотоков»;
  • «СтруктураДанныеМенеджера»
    • Служебные параметры (РазрезМенеджеров, СтруктураМодуляОбработкиСобытийРазработчика, СоотвествиеВедущийВедомые, СоотвествиеВедомыйВедущие, СоотвествиеОбъектРесурсы, СоотвествиеРесурсОбъекты, СоотвествиеПотокДанныеПотока, СоотвествиеОбъектПараметры, МаксимальнаяГлубинаОчереди)

Назначение: Позволяет выполнять произвольный алгоритм в самом начале запуска менеджера потоков, еще до запуска самих потоков.

Назначение в рамках восстановления партий: Создает временный объект (таблицу значений) для консолидации ошибок восстановления партий.

Вверх

Событие: «ПриПолученииМассиваРесурсов»

Место вызова: Код основной программы;

Принцип работы: Как функция. Допустимые типы данных:

Доступные параметры:

Назначение: Описывает алгоритм получения массива «МассивЗначенийРесурсов» (см. раздел «Расчет ресурса»). Данное событие нужно, только если необходимо формировать зависимость обработки одних объектов от других

Назначение в рамках восстановления партий: Заполняет массив ресурсов для возможности распараллелить процесс восстановления партий.

Вверх

Событие: «ПриОбработкеИсключенийИзОчередиМенеджера»

Место вызова: Код основной программы;

Принцип работы: Как функция. Допустимые типы данных:

  • Неопределено (по умолчанию — включить в очередь);
  • Булево (Истина — включить в очередь; Ложь — исключить из очереди).

Доступные параметры:

Назначение: Описывает алгоритм условий исключения объекта из очереди менеджера. По умолчанию все объекты добавляются в очередь менеджера.

Назначение в рамках восстановления партий: Исключает документы, не имеющие ресурсов, те по которым не надо восстанавливать последовательность.

Вверх

Событие: «ПриОпределенииТипДанныхВПотоке»

Место вызова: Фоновое задание «МенеджерПотоков» / Фоновые задания потоков;

Принцип работы: Как функция. Допустимые типы данных:

  • Неопределено (по умолчанию);
  • Строка (Допустимые значения «ДанныеДляПотока» / «ОтветПотока» / «Неопределено»).

Доступные параметры:

  • «ЗначениеПотока» — Структура, переданная в поток для обработки;

Назначение: Описывает алгоритм по которому определяется, что в «ЗначениеПотока» — храниться «ДанныеДляПотока» / «ОтветПотока» /  «Неопределено».

Назначение в рамках восстановления партий: Если в «ЗначениеПотока» переменная «Булево» — значит это «ОтветПотока». Да – документ восстановлен. Нет – ошибка при восстановлении. Если «Структура», то по умолчанию – это «ДанныеДляПотока», а если Неопределено – «Неопределено» — поток Свободен.

Вверх

Событие: «ПриОбработкеДействияПотока»

Место вызова: Фоновые задания потоков;

Принцип работы: Как функция. Допустимые типы данных:

  • Неопределено (по умолчанию);
  • Произвольный;

Доступные параметры:

  • «ЗначениеПотока» — Структура, переданная в поток для обработки;

Назначение: Содержит основной алгоритм обработки объекта.

Назначение в рамках восстановления партий: Вызывает процедуру восстановления партий по переданному документу.

Вверх

Событие: «ПриОбработкеОтветаПотока»

Место вызова: Фоновое задание «МенеджерПотоков»;

Принцип работы: Как процедура;

Доступные параметры:

  • «ИдПотока» (Тип: Уникальный идентификатор) – УИД фонового задания, вернувшего ответ;
  • «ОтветПотока» (Тип: Произвольный) – Данные возвращенные событием «ПриОбработкеДействияПотока»;
  • «СтруктураДанныеМенеджера» — см. событие «ПриЗапускеМенеджераПотоков»;
  • «ОбрабатываемыйОбъект» — ссылка на обрабатываемый объект (см. раздел «Процедура ОбработатьОбъект()»)

Назначение: Если требуется обрабатывать ответ от потока, то тут описывается что необходимо сделать.

Назначение в рамках восстановления партий: Если документ «провелся» — ничего не делаем J. Если же нет – тогда записываем информацию в таблицу значений описанную в событии «ПриЗапускеМенеджераПотоков».

Вверх

Событие: «ПриНевозможностиОбработатьОбъект»

Место вызова: Фоновое задание «МенеджерПотоков»;

Принцип работы: Как процедура;

Доступные параметры:

  • «СтруктураДанныеМенеджера» — см. событие «ПриЗапускеМенеджераПотоков»;
  • «ОбрабатываемыйОбъект» — ссылка на обрабатываемый объект (см. раздел «Процедура ОбработатьОбъект()»)

Назначение: Событие вызывается после всех попыток («ПределКоличествоПопытокОбработатьОбъект») обработать объект, но до очистки информации о нем в «Менеджере потоков». Позволяет, например, записать объект в ошибки и вывести информацию после завершения работы «МенеджераПотоков»

Вверх

Событие: «ПередЗавершениемМенеджераПотоков»

Место вызова: Фоновое задание «МенеджерПотоков»;

Принцип работы: Как процедура;

Доступные параметры:

Назначение: Позволяет выполнять произвольный алгоритм перед завершением менеджера потоков, но до очистки ХранилищеОбщихНастроек.

Назначение в рамках восстановления партий: Сохраняем заполненную таблицу значений, созданную в событии «ПриЗапускеМенеджераПотоков» во временном хранилище по адресу определенному в событии «ПередЗапускомМенеджераПотоков»

Вверх

Событие: «ПослеЗавершенияМенеджераПотоков»

Место вызова: Код основной программы;

Принцип работы: Как процедура;

Доступные параметры:

Назначение: Произвольный алгоритм, после того как дождались остановки «Менеджера потоков»

Назначение в рамках восстановления партий: Получаем таблицу значений с ошибками обработки документов и сохраняем ее на диск в формате Excel. На основании данной таблицы определяем куда переместить границы последовательности.

Вверх

Событие: «ПриПолученииМестаХраненияФайловМониторинга»

Место вызова: Код основной программы;

Принцип работы: Как функция. Допустимые типы данных:

Назначение: Определяет место сохранения файлов отчетов мониторинга, если он был включен при инициализации менеджера потоков.

Вверх

Вариант передачи данных между событиями

Upd: Теперь используется новый механизм обмена  — Универсальный менеджер потоков 2.0

Вверх

Отчеты

Upd: Отчеты обновлены — Универсальный менеджер потоков 2.0

По умолчанию предоставлена возможность формировать 3 отчета:

  • «Мониторинг порядок обработки» — фиксирует на какой итерации «Менеджера потоков» завершилась обработка объектов. Состав:
    • «Ссылка» — Ссылка на обработанный объект;
    • «НомерИтерации» — Номер итерации «Менеджера потоков» на которой завершилась обработка объекта.
  • «Мониторинг потоков» — фиксирует на каждой итерации «Менеджера потоков» — количество объектов в «Очереди для потоков», количество занятых потоков и количество отработанных объектов. Состав:
    • «ВремяВмс» — ТекущаяУниверсальнаяДатаВМиллисекундах();
    • «НомерИттерации» — Номер итерации «Менеджера потоков» на которой снимаются значения;
    • «ОбъектовВОчереди» — количество объектов в «Очереди для потоков»;
    • «КоличествоЗанятыхПотоков» — количество потоков, занятых на текущей итерации;
    • «КоличествоОбработанныхОбъектов» — количество объектов завершивших свою обработку на текущей итерации;
  • «Мониторинг очереди менеджера» — фиксирует количество документов в «Очереди менеджера». Состав:
    • «ВремяВмс» — ТекущаяУниверсальнаяДатаВМиллисекундах();
    • «ОбъектовВОчередиМенеждера» — Общее количество документов в «Очереди менеджера»;

Их включение осуществляется в процедуре «ИнициализироватьМенеджерПотоков()» (См. Раздел «Функция ИнициализироватьМенеджерПотоков()»)

«Мониторинг порядок обработки» и «Мониторинг потоков» заполняются в фоновом задании «Менеджера потоков», а «Мониторинг очереди менеджера» в коде основной программы.

«Мониторинг потоков» и «Мониторинг очереди менеджера» — в большинстве своем больше информационные и позволяют построить графики. Графики из рассматриваемого примера «Восстановление партий»:

Ноябрь 2016 мониторинг потоков (полный)

Ноябрь 2016 мониторинг потоков (начало укрупненно)

Ноябрь 2016 Мониторинг очереди менеджера

графики по всем месяцам в архиве

На всех графиках «Мониторинг очереди менеджера» последней «прямолинейный» спуск — это обработка документов в процедуре «ДождатьсяОстановкиМенеджераПотоков()» уже после того как отработал основной цикл перебора документов в последовательности.

Количество отчетов можно расширить с помощью функции «ОбработатьСобытиеРазработчика()». При восстановлении партий формируется дополнительный отчет по необработанным документам с описанием ошибки. Так же на основании данного отчета определяется куда перенести границу последовательности после окончания работы восстановления партий.

Все отчеты сохраняются в файл на том компьютере, откуда вызван основной цикл обхода документов. Место сохранения описывается в функции «ОбработатьСобытиеРазработчика()», событие «ПриПолученииМестаХраненияФайловМониторинга».

Вверх

Демо обработки

Каждая обработка позволяет вызывать любой способом месторасположение функции «ОбработатьСобытиеРазработчика()» (см. раздел «Месторасположение функции «ОбработатьСобытиеРазработчика()»»):

  • В общем модуле «МенеджераПотоков»
  • В произвольном модуле БД
  • Во внешней обработке

Все инструкции, что необходимо сделать написаны в каждой обработке в модуле объекта.

В демо примерах представлены 2 вида обработок выполняющие одно действие:

1. Формирование расчетных листов по сотрудникам и сохранение их на ПК (только для УПП 1.3).

В каждой обработке есть 2 способа формирования расчетных листков («независимый» и с построением зависимости объектов), и три варианта обработки результата, что в конечном итоге дает 6 вариантов обработки:

  • Независимое формирование (сохраняем на сервере потока);
  • Независимое формирование (сохраняем на сервере менеджера);
  • Независимое формирование (сохраняем на клиенте);
  • Зависимость по 1-ой букве (сохраняем на сервере потока);
  • Зависимость по 1-ой букве (сохраняем на сервере менеджера);
  • Зависимость по 1-ой букве (сохраняем на клиенте);

«Независимое формирование» — Это формирование отчетов полностью параллельно, без всякой зависимости.

«Зависимость по 1-ой букве» — это формирование с построением зависимости (графа), где сотрудники, фамилии которых начинаются на одну и ту же букву выстраиваются в очередь, а если буквы не совпадают, то как при независимом формировании (зависимость ненесет ни какой практической цели — просто коказано как ее добиться).

3 варианта обработки результата, показывают, как происходит обмен данными между основной программой / Менеджером потоков / фоновыми заданиями.

Варианты обработки (от простого к сложному – по количеству кода):

  • (сохраняем на сервере потока) – В данном варианте передача данных идет только от клиента, через "менеджер потоков" на потоки, где каждый поток сохраняет файл;
  • (сохраняем на сервере менеджера) – тут посложнее, данный вариант повторяет первый, но файл не сохраняется в потоке, а ответ (табличный документ) передается обратно в менеджер потоков, где данные консолидируются и в конце перед завершением менеджера потоков файлы начинают сохраняться на сервер, где работал менеджер потоков.
  • (сохраняем на клиенте) – ну и самый сложный вариант, повторяет второй, но опять файлы не сохраняются на диск, а передаются через временное хранилище на клиент, где и производят сохранение данных на диск.

Итого для ознакомления предоставлено 18 примеров работы (3 варианта расположения * 2 способа формирования * 3 варианта обработки результата)

Таблица возможности запуска обработки (Только для УПП 1.3):

Вызов событий ДемоДля разработчикаПолная
В произвольном модуле+++
Во внешней (этой) обработке+-*-/+**
В модуле менеджера потоков-***-***+

"+" — можно запустить

"—" — нельзя запустить

* — из-за безопасного режима;

** — по умолчанию безопасный режим включен, но его можно отключить;

*** — из-за закрытого кода.

2. Перезапись N-элементов произвольного справочника (любая БД)

 В каждой обработке есть 2 способа перезаписи "независимы" и с зависимостью

"Независимая перезапись" — это перезапись полностью параллельно без всякой зависимости;

"Зависимость по четности кода" — выстраивает очередь по четным и нечетным кодам (инициализировать можно любое количество потоков, но одновременно будет занято 1-2 потока)

Вот результат простой перезаписи 500 ед. номенклатуры в УПП (колебания от 9 до 16 потоков между 7-8 сек связаны скорее всего с тем, что начало/конец замера происходили вначале/вконце секунды):

Таблица возможности запуска обработки:

Вызов событий ДемоДля разработчикаПолная
В произвольном модуле+++
Во внешней (этой) обработке++-/+*
В модуле менеджера потоков+**-***+

"+" — можно запустить

"—" — нельзя запустить

* — по умолчанию безопасный режим включен, но его можно отключить;

** — код закрыт, но для данной обработки код уже встроен;

*** — из-за закрытого кода;

Вверх

Менеджер потоков (Демо)

Upd: Полная версия, полностью открытый код и только за $m. — Универсальный менеджер потоков 2.0

Предоставил файл поставки конфигурации с общим модулем (закрыт от редактирования). Имеет ряд ограничений по сравнению с полной версией:

  • Максимальное количество потоков = 3;
  • Значения в общих настройках сохраняются с префиксом "Демо_";
  • Обработка событий разработчика из внешних обработок в НЕ безопасном режиме;
  • "Замедленно" получение Значений из хранилища общих настроек;
  • Используется не оптимальный (ранний вариант) способ передачи данных между основной программой и "Менеджером потоков";
  • Используется не оптимальный (ранний вариант) построение графа.

А так все работает. Как писал выше, для Вас модуль не представляет интереса, весь свой функционал надо выложить в функцию "ОбработатьСобытиеРазработчика()". Как? Смотрите Демо обработки. 

Вверх

Заключение

Upd: Продолжение — Универсальный менеджер потоков 2.0

Вот теперь, наверное, можно сказать, что я удовлетворил свое любопытство и с пользой потратил свободное время :). 

Если сообщество будет заинтересовано в дальнейшем развитии данного механизма, то думаю это вполне можно реализовать. Как вариант дальнейшего развития вижу:

  • Дополнительно реализовать для управляемых форм с переводом в асинхронный режим;
  • Добавление новых событий;
  • Формирование графа зависимости, как отчета, с весом каждого ребра;
  • Программное формирование отчетов мониторинга на СКД без необходимости сохранять их в файл на клиенте;
  • И прочие доработки…

Вверх

Обновления

Обновление 2018 02 07:

Обновление 2017 07 13:

Новое в версии v1.0.1

  • Изменен механизм Инициализации менеджера потоков;
    • Изменен способ указания "МодульОбработкиСобытийРазработчика " если алгоритмы во внешней обработке. Ранее надо было передать путь к обработке, но в связи с адаптацией под УФ необходимо передать ДвоичныеДанные (пример в Демо обработке — "перезапись элементов справочников").
  • Добавлена функция ПолучитьСтруктуруПараметровИнициализацииМенеджераПотоков;
    • Добавлен механизм «попыток» обработать объект;
    • Добавлена возможность управлять размером «Очереди потоков».
  • Добавлено событие ПриНевозможностиОбработатьОбъект;
  • Код адаптирован под управляемые формы (без модальности и синхронных вызовов);
  • Демо обработка «Перезапись элементов справочников» получила управляемую форму;
  • Демо обработка «Интерактивная остановка менеджеров потоков» получила управляемую форму;
  • Исправлены ошибки.

Статья:

  • Внесены исправления в тексте под новую версию;
  • Исправлены ошибки;

Обновление 2017 06 09:

В статью добавлены Примеры формирования ресурсов

has been added to your cart:
Оформление заказа