Обновление для всех!
Еще больше возможностей, еще быстрее обработка, еще проще разработка - Универсальный менеджер потоков 2.0.
Полная версия, полностью открытый код и только за $m.
Данный материал переходит в разряд статьи
Очень кратко, о чем речь…
Фреймворк в виде одного общего модуля, позволяющего при получении объектов на обработку запускать их в несколько потоков. Особенности:
- Нет необходимости рассчитывать «порции» для обработки;
- Нет необходимости организовывать файловый обмен между потоками;
- Возможность запускать несколько менеджеров потоков одновременно, при этом потоки одного менеджера, могут запускать новые менеджеры со своими задачами и потоками (главное чтоб лицензий хватило :));
- Можно выстраивать граф зависимости объектов, что позволяет, например, избегать взаимоблокировок и/или организовать восстановление партий (на нашем предприятии удалось добиться 10х+ ускорения при 10 потоках в рабочее время – 200+ активных пользователей - Результаты работы механизма);
- Можно и нужно производить вмешательство в алгоритмы с помощью событий;
- Возможность описывать алгоритмы событий, как в модуле менеджера, так и в любом другом модуле БД (предпочтительно), а также во внешней обработке.
- Автоматический рестарт потока в случае ошибок;
- Контроль за количеством рестартов по каждому объекту;
- Возможность получать «ответы» от потоков;
- Возможность контролировать работу с помощью «Инструментов разработчика» или иных отчетов;
- Возможность срочного прерывания работы;
- И многое другое…
О том, как оно все работает описано ниже, при желании можно и свое написать :)
Буков очень много, но и картинок достаточно :)
Оглавление
Пример 1 (По складам - для восстановления партий не подходит)
Пример 2 (По складам - для восстановления партий подходит)
Пример 3 (По складам и номенклатуре - для восстановления партий не подходит)
Пример 4 (По складам и номенклатуре - для восстановления партий не подходит)
Пример 5 (По складам и номенклатуре - для восстановления партий подходит)
Пример 6 (Варианты на одном примере)
Обновление «Очереди для потоков»
Функция ПолучитьСтруктуруПараметровИнициализацииМенеджераПотоков()
Функция ИнициализироватьМенеджерПотоков()
Процедура «ОбработатьОбъект()»
Функция «ОбработатьСобытиеРазработчика()»
Месторасположение функции «ОбработатьСобытиеРазработчика()»
В общем модуле «МенеджераПотоков»
В произвольном модуле БД (рекомендуемый)
События функции «ОбработатьСобытиеРазработчика()»
Событие: «ПередЗапускомМенеджераПотоков»
Событие: «ПриЗапускеМенеджераПотоков»
Событие: «ПриПолученииМассиваРесурсов»
Событие: «ПриОбработкеИсключенийИзОчередиМенеджера»
Событие: «ПриОпределенииТипДанныхВПотоке»
Событие: «ПриОбработкеДействияПотока»
Событие: «ПриОбработкеОтветаПотока»
Событие: «ПриНевозможностиОбработатьОбъект»
Событие: «ПередЗавершениемМенеджераПотоков»
Событие: «ПослеЗавершенияМенеджераПотоков»
Событие: «ПриПолученииМестаХраненияФайловМониторинга»
Вариант передачи данных между событиями
Введение
В данной публикации будет максимально подробно «разжеван» способ реализации «Менеджера потоков», а так же предоставлены демо обработки с готовым открытым исходным кодом.
Описание и примеры с кодом, в данной статье, будут даны в общих чертах по принципу от общего к частному. На каких-то скринах будут отсутствовать параметры процедур и функций или строки кода, в связи с тем, что в данной конкретной теме это не является существенным.
Все повествование будет вестись на примере «Восстановления партий», т.к. эта задача была первоочередной, но в дальнейшем переродилась в «Универсальный механизм». «Универсальным» он назван по той причине, что общий модуль, где располагаются алгоритмы «Менеджера потоков» могут быть обособлены и не изменны на всем протяжении использования механизма, но при этом решать разные задачи (восстановление партий, расчет зарплаты, формирование пакетов документов, формирование отчетов и т.д.).
Весь код и в скринах, и в обработках написан на обычных формах, т.к. разработка велась на базе УПП. Описание предоставлено в рамках «Восстановления партий».
Но обо всем по порядку …
Результаты работы механизма
При распараллеливании на 10 потоков.
Показатель | Ноябрь 2016 | Декабрь 2016 | Январь 2017 | Февраль 2017 |
---|---|---|---|---|
Документов в последовательности (шт.) | 22865 | 18298 | 14788 | 17189 |
Документов для восстановления (шт.) | 14192 | 9252 | 8537 | 9921 |
Однопоточное восстановление («холодный»/«прогретый») (мин.) | 293/265 | 215/196 | 172/162 | 219/203 |
Параллельное восстановление («холодный»/«прогретый») (мин.) | 30/24 | 20/16 | 16/14 | 19/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/265 | 215/196 | 172/162 | 219/203 |
Однопоточное восстановление + оптимизация («холодный»/«прогретый» ) (мин.) | 130/108 | 85/67 | 67/54 | 76/62 |
Параллельное восстановление («холодный»/«прогретый») (мин.) | 30/24 | 20/16 | 16/14 | 19/17 |
Это уже позволяло в критической ситуации (1 сессия в БД с блокировкой доступа) провести восстановление квартала за 1 рабочий день.
Далее, было желание реализации фоновых заданий. Решил попробовать схему описанную «SoftPoint», т.к. она более детально и подробно описана, но при было желание избавиться от минусов прошлой разработки.
На удивление решение оказалось значительно проще прошлогодних алгоритмов, за исключением одного момента, а именно управления документами в очередях. Так же мне «не давала покоя» реализация по принципу «у каждого потока своя очередь». В итоге я приступил к новой разработке, результатами которой и решил поделиться со всеми. И так поехали…
Общая схема
Данная схема показано очень упрощенно, дабы не испугать не искушенного. Как видно на рисунке необходимо изменить однопоточное проведение в цикле, на проведение в несколько потоков.
В общем случае потребуется внести 3 корректировки в типовой код:
- Перед циклом запустить инициализацию менеджера потоков;
- В цикле переопределить процедуру выполнения;
- После цикла дождаться завершения работы менеджера.
Общие описание каждой из процедур основного кода:
- Функция ИнициализироватьМенеджерПотоков() - предназначена для инициализации работы в потоках и установки начальных параметров менеджера потоков;
- Процедура ОбработатьОбъект() - производит первичные расчеты по объекту и передает его при необходимости в менеджер потоков;
- Процедура ДождатьсяОстановкиМенеджераПотоков() - ожидает завершения работы всех фоновых заданий, а так же производит сохранение всех отчетов мониторинга.
Общие описание основных процедур фонового задания «Менеджер потоков»:
- Функция ОбновитьОчередьОбъектов() – очищает "Очередь для потоков" от объектов если они уже обработаны, при необходимости перезапускает потоки, также определяет какие потоки свободны;
- Процедура ЗапуститьОбъектыИзОчередиВПоток () - производит передачу объектов из «Очереди для потоков» в свободные потоки;
- Процедура ДобавитьОбъектВОчередь() - добавляет объект в "Очередь для потоков" если есть свободное место;
Запуск и остановка ФЗ
Контроль запуска и остановки фоновых заданий очень важен, т.к. напрямую на них влиять «не удобно». Для исключительных ситуаций, например, не правильно выставлены начальные настройки, предоставлена простая обработка - «Интерактивная остановка менеджеров потоков». Ну или просто можно вызвать процедуру «МенеджерПотоков. ОстановитьМенеджерПотоковИнтерактивно()»
На данном рисунке видно, что все фоновые задания запускаются из процедуры «ИнициализироватьМенеджерПотоков». Сначала запускается менеджер потоков, а уже он запускает фоновые задания потоков. В каждом фоновом задании, включая «Менеджер потоков» запускается «бесконечный цикл». На каждой итерации цикла, потоки отслеживают активность «Менеджера потоков» и если он не активен, они завершают свою работу. В то же время, цикл основной программы, так же на каждой итерации проверяет активность «Менеджера потоков» и в случае его преждевременного завершения вызывает ошибку в основной программе.
После того, как цикл основной программы был завершен, осуществляется установка переменной «ОбъектыЗакончились» в значение «Истина», затем запускается «бесконечный цикл» с ожиданием остановки «Менеджера потоков».
«Менеджер потоков» на каждой итерации своего «Бесконечного цикла» анализирует 3 параметра:
- ОбъектыЗакончились – значение переменной переданной из основной программы со значением «Истина» сообщает о том, что новых объектов в «Менеджер потоков» не поступит;
- КоличествоОбъектовВОчереди – говорит само за себя, количество объектов в «Очереди для потоков»;
- КоличествоЗанятыхПотоков – так же говорит само за себя;
Как только выполняется «условие выхода» из «Бесконечного цикла» - «Менеджер потоков» завершает свою работу.
Основная программа «увидев» не активность «Менеджера потоков» выходит из «бесконечного цикла».
Передача данных между ФЗ
Это был один из самых важных вопросов в решении данной обработки, т.к. хотелось реализовать возможность доработки с минимальным вмешательством в типовой код и в структуру метаданных, без создания таблиц временного хранения данных.
«Хранилище общих настроек» подошло как нельзя кстати. Оно обладает как минимум 2ми плюсами:
- Хранит данные в разрезе пользователей ИБ;
- Хранит «Произвольный» тип данных.
Наблюдать «в живую», как происходит передача данным между фоновыми заданиями можно с помощью «Инструментов разработчика» - //infostart.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:
В статью добавлены Примеры формирования ресурсов