Восстановление партий или взаиморасчетов, расчет зарплаты, пакетное формирование документов или отчетов - теперь все это стало доступнее.
* Есть желание повысить скорость работы медленных алгоритмов! Но...
* Нет времени думать о реализации многопоточности?
* о запуске и остановке потоков?
* о поддержании потоков в рабочем состоянии?
* о передаче данных в потоки и как получить ответ из потока?
* об организации последовательности?
Тогда ЭТО - то что надо!!!
(82)Внедрил успешно подсистему, проблемный, долгий расчет себестоимости в УПП ускорен ~10 раз, очень ценный продукт, большое спасибо за труд, автор очень отзывчивый, всегда был рад помочь, за что отдельное спасибо, однозначно забрал данный продукт в свой арсенал, пригодится на крупных проектах, уже есть варианты, где буду дальше применять
(18)видимо в спойлерах не ищет(( доберусь до компа перепроверю через "источник". В обработке поправлено, видимо пока готовил статью в Ворде не заметил). Спасибо.
(9) А как ожидать завершения? По таймеру проверять?
Суть то в том, чтобы запустить пачку заданий и при завершении хотя бы одного тут же выдать новое задание с новой порцией данных. Так можно максимально утилизировать процессор и управление потоками становится тривиальным
(11) Можно по таймеру, можно по значению переменной (в текущей реализации она также сохраняется в общих настройках) и мониторить ее на каждой итерации.
(13) На сколько я понимаю, в Вашей реализации вы предлагаете задействовать, недавние вирусы (meltdown и spectre), тогда возможно получиться получать ответ сразу как задание выполнено :)
(20) Есть еще несколько идей (осталось только время найти для их воплощения). Они пока не реализованы, т.к. реализуй я их, то текущую версию выложил бы еще не скоро. Так основные задумки все работают - можно смело пользоваться.
А каким образом происходит восстановление партий в несколько потоков? Например, для того, чтобы восстановить партию, мне нужно знать остатки по номенклатуре на дату, а пока предыдущий поток не завершится этих данных не будет.
(21) Артем, для ответа на Ваш вопрос, я рекомендую Вам ознакомится первым постом и с текущим. В первом посте вообще все рассказывалось отталкиваясь именно от этой задачи.
Для простоты понимания посмотрите примеры из первого поста
Добрый день, очень интересная статья, спасибо за труд.
Скажите:
1. Применимо для восстановление партий + оценка стоимости по средней ?
2. Можно краткий пример как это все запустить для п1, в частности как и у вас для конфигурации УПП.
1. Применимо для восстановление партий + оценка стоимости по средней ?
Применимо для любого учета, кроме разве что - РАУЗ (хотя может и там сработает не проверял).
Все процедуры восстановления - ТИПОВЫЕ с небольшими оговорками о них ниже...
Что у нас есть в типовом учете:
1. У нас есть обработка "Проведение по партиям". В ней процедура "КнопкаВыполнитьНажатие", которая в свою очередь, так или иначе, вызывает "ЗаполнениеДокументов.ВыполнитьВосстановление".
2. В рамках этой процедуры обрабатывается последовательность документов и каждый документ последовательности обрабатывается с помощью "УправлениеЗапасамиПартионныйУчет.ДвижениеПартийТоваров(..." (по крайне мере основная масса документов списания).
Все, что необходимо сделать - это чтобы эта строка кода выполнялась в событии "ПриОбработкеДействияПотока" со всеми своими параметрами
для этого необходимо следующее:
1. Перед началом цикла "Пока ЕстьДокументы Цикл" получить параметры менеджера потоков, установить параметры и провести его инициализацию
2. В цикле вместо "УправлениеЗапасамиПартионныйУчет.ДвижениеПартийТоваров (..." вызвать метод менеджера потоков "ОбработатьОбъект", куда параметрами передать а) СтруктуруПараметровМенеджера, б) ссылку на документ в) Структуру (или любую другой коллекцию) со всеми параметрами из типовой "УправлениеЗапасамиПартионныйУчет.ДвижениеПартийТоваров (..."
3. После цикла вызвать метод "ДождатьсяОстановкиМенеджераПотоков" куда передать только СтруктуруПараметровМенеджера.
Все больше в типовой обработке ни чего править не надо.
Дальше идет работа с событиями, что использовалось у Нас:
1. "ПередЗапускомМенеджераПотоков" Создали массив(пустую) для учета документов восстановление по которым не получилось;
2. "ПриПолученииРесурсов" Это основное событие распараллеливания - тут по каждому документу необходимо собирать его ресурсы. Как? Смотрите примеры из презентации или статьи
3. "ПриДобавленииВОчередьОбработки" - тут все просто, если ресурсы есть - возвращаем "Истина", если их нет - "Ложь". Кода возвращается "Истина", объект помещается в граф и по нему рассчитываются связи в зависимости от ресурсов (следующее событие "ПриОбработкеДействияПотока"), а если "Ложь", то объект - пропускается (следующее событие "ПриОбработкеПропуска")
4. "ПриОбработкеДействияПотока" собственно вызываем нашу строчку кода "УправлениеЗапасамиПартионныйУчет.ДвижениеПартийТоваров(..." со всеми параметрами. Результатом данного метода могут быть произвольные данные (ловятся в событии "ПриОбработкеОтвета")
5. Надо зафиксировать факт НЕ обработки объекта - это можно сделать в 2х событиях: "ПриОбработкеОшибки" - если поток падал в момент обработки объекта (по умолчанию до 5 раз пытается обработать объект) и в событии "ПриОбработкеОтвета" можно, например, при обработке события "ПриОбработкеДействияПотока" возвращать значение переменной "Отказ" если оно "Истина", в этом случае мы заносим объект в структуру определенную в п1.
6. "ПослеЗавершенияМенеджераПотоков" собственно - это последнее событие в нем мы производим установку границы последовательности. Если массив из п1 - пуст, то на самый последний документ последовательности в периоде, а если в массиве есть хоть один документ, то границу устанавливаем на самый ранний.
Для примера:
Количество строк кода во всех событиях: ~400
Самое большое событие: "ПриПолученииРесурсов" ~ 150 строк
Самое маленькое событие: "ПриДобавленииВОчередьОбработки" - 1 строка (Возврат пПараметрыСобытия.СтруктураДанных.МассивРесурсов.Количество() > 0;)
P.S. Один из не маловажных моментов :)
Код написанный в цикле процедуры "ВыполнитьВосстановление" - выполняется в транзакции, так вот: перед выполнением метода "ОбработатьОбъект" рекомендуется ее зафиксировать, а сразу за ним Начать новую. Кроме того в событии "ПриОбработкеДействияПотока" строку "УправлениеЗапасамиПартионныйУчет.ДвижениеПартийТоваров(..." - наоборот заключить в транзакцию
P.P.S. У нас помимо "УправлениеЗапасамиПартионныйУчет.ДвижениеПартийТоваров(..." в событии "ПриОбработкеДействияПотока" вызывается еще и "УправлениеПроизводствомДвиженияПоРегистрам.ПровестиДокументПоПроизводственнымРегистрам(..."
2. "ПриПолученииРесурсов" Это основное событие распараллеливания - тут по каждому документу необходимо собирать его ресурсы. Как? Смотрите примеры из презентации или статьи
Доброго дня.
А можно привести пример кода для формирования ресурса и как потом им пользоваться. Я в этом месте застрял.
А можно привести пример кода для формирования ресурса и как потом им пользоваться.
Ресурсами ни как пользоваться не надо ими пользуется "менеджер потоков" главное правильно их сформировать (тут пример в примерах, на картинках, см. строку "Массивы" надо сформировать массив массивов)
Вот примерный код:
СтруктураДанных = пПараметрыСобытия.СтруктураДанных;
ОбрабатываемыйОбъект = СтруктураДанных.ОбрабатываемыйОбъект;
ПараметрыДляОбъекта = СтруктураДанных.ПараметрыДляОбъекта;
МассивРесурсов = Новый Массив;
ТаблицаСписания = УправлениеЗапасамиПартионныйУчет.ПолучитьТаблицуСтрокДокументов(ОбрабатываемыйОбъект,
ПараметрыДляОбъекта.Упр,
ПараметрыДляОбъекта.Бух,
ПараметрыДляОбъекта.Нал);
Для каждого СтрокаСписания из ТаблицаСписания Цикл
МассивРесурса = Новый Массив;
МассивРесурса.Добавить(СтрокаСписания.Номенклатура);
МассивРесурса.Добавить(СтрокаСписания.Склад);
МассивРесурсов.Добавить(МассивРесурса);
КонецЦикла;
Возврат МассивРесурсов;
Дальше идет работа с событиями, что использовалось у Нас:
1. "ПередЗапускомМенеджераПотоков" Создали массив(пустую) для учета документов восстановление по которым не получилось;
2. "ПриПолученииРесурсов" Это основное событие распараллеливания - тут по каждому документу необходимо собирать его ресурсы. Как? Смотрите примеры из презентации или статьи
3. "ПриДобавленииВОчередьОбработки" - тут все просто, если ресурсы есть - возвращаем "Истина", если их нет - "Ложь". Кода возвращается "Истина", объект помещается в граф и по нему рассчитываются связи в зависимости от ресурсов (следующее событие "ПриОбработкеДействияПотока"), а если "Ложь", то объект - пропускается (следующее событие "ПриОбработкеПропуска")
4. "ПриОбработкеДействияПотока" собственно вызываем нашу строчку кода "УправлениеЗапасамиПартионныйУчет.ДвижениеПартийТоваров(..." со всеми параметрами. Результатом данного метода могут быть произвольные данные (ловятся в событии "ПриОбработкеОтвета")
5. Надо зафиксировать факт НЕ обработки объекта - это можно сделать в 2х событиях: "ПриОбработкеОшибки" - если поток падал в момент обработки объекта (по умолчанию до 5 раз пытается обработать объект) и в событии "ПриОбработкеОтвета" можно, например, при обработке события "ПриОбработкеДействияПотока" возвращать значение переменной "Отказ" если оно "Истина", в этом случае мы заносим объект в структуру определенную в п1.
6. "ПослеЗавершенияМенеджераПотоков" собственно - это последнее событие в нем мы производим установку границы последовательности. Если массив из п1 - пуст, то на самый последний документ последовательности в периоде, а если в массиве есть хоть один документ, то границу устанавливаем на самый ранний.
Дошел до событий, дабы не городить костыли - можно пример кода по каждому из событий для восст. по партиям?
Дошел до событий, дабы не городить костыли - можно пример кода по каждому из событий для восст. по партиям?
В рамках данной статьи это не предусмотрено.
Постараюсь собраться с силами и выложить новую со всеми кодами для восстановления партий на нашем примере :)
Вам могу, пока, посоветовать "городить костыли" заодно опробуете все сами.
Рекомендации:
0) Поднимите копию базы и сделайте там первое полное восстановление за месяц (это будет эталон для сравнения)
1) разработку рекомендую начать в отдельной базе с 1 потока;
2) восстановление делайте в рамках 1 дня;
3) для сверки пользуйтесь "Ведомость по партиям товаров на складах"
4) как добьетесь результата на 1 потоке увеличивайте их количество до 2-3, если и на них все будет гладко, то ставьте, то количество которое потянет ваш сервер :) (У нас восстановление делается на 10 потоках - этого для нас достаточно. Но была задача по непосредственному удалению документов из БД, там писали обработку и удаляли на 45 потоках. Все зависит от специфики, задачи, железа и т.д.)
Для восстановление выше приведенного кода(с расчетом ресурсов) не достаточно - все зависит от специфики Вашего предприятия. В нашем дополнительно еще собираются ресурсы по производственной части.
Так что, дерзайте!
P.S. Я надеюсь у Вас управляемый режим блокировок?
Подскажите, что нужно сделать, что-бы сработал механизм формирования ресурсов.
Запускаю потоки через "мпМенеджерПотоков.ОбработатьКоллекциюОбъектов".
2. "ПриПолученииРесурсов" Это основное событие распараллеливания - тут по каждому документу необходимо собирать его ресурсы. Как? Смотрите примеры из презентации или статьи
Событие "ПриПолученииРесурсов" предназначено только для метода "ОбработатьОбъект" - когда по объектам необходимо строить граф.
Рекомендую посмотреть презентацию с IE2018 (ссылка есть в публикации) или тут.
Необходимый минимум для метода "ОбработатьКоллекциюОбъектов" показан тут.
Пока прикладываю схему доступности событий от методов
Подскажите что я делаю не так:
1. Получаю параметры "ПолучитьСтруктуруПараметровИнициализацииМенеджераПотоков"
2. Инициализирую МП "ИнициализироватьМенеджерПотоков"
3. В цикле обхожу выборку документов методом "ОбработатьОбъект"
4. После цикла ожидаю завершения МП "ДождатьсяОстановкиМенеджераПотоков"
Получаю ошибку:
Поле объекта не обнаружено (АлгоритмыРаботыСКоллекцией)
КодСоздания = пСтруктураПараметров.ПараметрыИнициализации.ПараметрыОбработкиКоллекции.АлгоритмыРаботыСКоллекцией.КодСоздания;
В структуре "ПараметрыОбработкиКоллекции" действительно нет "АлгоритмыРаботыСКоллекцией".
Перед циклом дописал:
КодСоздания = "КоллекцияПриемник = Новый СписокЗначений;";
КодДобавления = "ЗаполнитьЗначенияСвойств(КоллекцияПриемник.Добавить(), КоллекцияИсточник[ИндексКоллекции]);";
Структура = Новый Структура;
Структура.Вставить("КодСоздания" , КодСоздания);
Структура.Вставить("КодДобавления", КодДобавления);
СтруктураПараметромМП.ПараметрыИнициализации.ПараметрыОбработкиКоллекции.Вставить("АлгоритмыРаботыСКоллекцией", Структура);
(41) пункты с 1 по 4 - правильные
Но вот код вызывающий у Вас ошибку срабатывать не должен. Он относится к методам работы с коллекциями.
И встречается в 2х местах:
Функция ПолучитьДанныеИзМенеджераПотоков
...
ИначеЕсли РезультатОбработки = "ДополненныйФрагментКоллекции" Тогда
...
и
Функция ОбработатьКоллекцию
которая в свою очередь вызывается из метода "ОбработатьКоллекциюОбъектов" и "ДополнитьКоллекциюОбъектов"
Версия менеджера у Вас 2.0.5? (не могу определить дату скачивания - не вижу Вас среди скачавших)
Можете мне прислать замер производительности по работе ФЗ "менеджера потоков"? (например через вотсап - номер в профиле)
и Код используемой обработки или саму обработку.
(42) Не вижу номера в профиле, возможно нужно быть в друзьях. Версия 2.0.5. Скачивался МП с другого аккаунта "Cruciann".
Сообщить("Обработка в потоках.");
ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
СтруктураПараметров = векМенеджерПотоков.ПолучитьСтруктуруПараметровИнициализацииМенеджераПотоков("ОбработатьКоллекциюДокументовОчередипереобеспечения","");
векМодульМенеджераПотоков.ПолучитьПараметрыМП("ЗаказПоставщику",СтруктураПараметров);
СтруктураПараметромМП = векМенеджерПотоков.ИнициализироватьМенеджерПотоков(СтруктураПараметров);
#Область Костыли
КодСоздания = "КоллекцияПриемник = Новый СписокЗначений;";
КодДобавления = "ЗаполнитьЗначенияСвойств(КоллекцияПриемник.Добавить(), КоллекцияИсточник[ИндексКоллекции]);";
Структура = Новый Структура;
Структура.Вставить("КодСоздания" , КодСоздания);
Структура.Вставить("КодДобавления", КодДобавления);
СтруктураПараметромМП.ПараметрыИнициализации.ПараметрыОбработкиКоллекции.Вставить("АлгоритмыРаботыСКоллекцией", Структура);
#КонецОбласти
Для Каждого ДокументСсылка Из Коллекция Цикл
СтруктурапараметровОбъекта = Новый Структура;
СтруктурапараметровОбъекта.Вставить("Период",ДокументСсылка.Период);
векМенеджерПотоков.ОбработатьОбъект(СтруктураПараметромМП,ДокументСсылка.Документ,СтруктурапараметровОбъекта);
КонецЦикла;
векМенеджерПотоков.ДождатьсяОстановкиМенеджераПотоков(СтруктураПараметромМП);
ВремяКонцаВыполнения = ТекущаяУниверсальнаяДатаВМиллисекундах();
ВремяВыполненияВМиллисекундах = ВремяКонцаВыполнения - ВремяНачала;
Сообщить("Окончание потоковой обработки: "+ВремяВыполненияВМиллисекундах / 1000);
Показать
Процедура ПолучитьПараметрыМП(ОбъектОбработки,СтруктураПараметров) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| векНастройкиМногопоточности.МодульОбработкиСобытийРазработчика КАК МодульОбработкиСобытийРазработчика,
| векНастройкиМногопоточности.МинимальноеКоличествоКоллекции КАК МинимальноеКоличествоКоллекции,
| векНастройкиМногопоточности.КоличествоПотоков КАК КоличествоПотоков,
| векНастройкиМногопоточности.КоличествоЭлементовКолекцииНаПоток КАК КоличествоЭлементовКолекцииНаПоток,
| векНастройкиМногопоточности.КоэффициентКратностиОчередиПотоковКПотокам КАК КоэффициентКратностиОчередиПотоковКПотокам,
| векНастройкиМногопоточности.ПределКоличествоПопытокОбработатьОбъект КАК ПределКоличествоПопытокОбработатьОбъект
|ИЗ
| РегистрСведений.векНастройкиМногопоточности КАК векНастройкиМногопоточности
|ГДЕ
| векНастройкиМногопоточности.Активно
| И векНастройкиМногопоточности.ОбъектОбработки = &ОбъектОбработки";
Запрос.УстановитьПараметр("ОбъектОбработки", ОбъектОбработки);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
СтруктураПараметров.ПараметрыОбщие.Вставить("Активно",Ложь);
Если Выборка.Следующий() Тогда
Если ЗначениеЗаполнено(Выборка.МодульОбработкиСобытийРазработчика) Тогда
СтруктураПараметров.ПараметрыИнициализации.МодульОбработкиСобытийРазработчика = Выборка.МодульОбработкиСобытийРазработчика;
КонецЕсли;
Если ЗначениеЗаполнено(Выборка.КоличествоПотоков) Тогда
Если ТипЗнч(Выборка.КоличествоПотоков) = Тип("Число") Тогда
СтруктураПараметров.ПараметрыИнициализации.КоличествоПотоков = Выборка.КоличествоПотоков;
КонецЕсли;
Если ТипЗнч(Выборка.КоличествоПотоков) = Тип("Булево") Тогда
СтруктураПараметров.ПараметрыИнициализации.ПараметрыОбработкиКоллекции.ДинамическийРассчетКоличестваПотоков = Выборка.КоличествоПотоков;
КонецЕсли;
КонецЕсли;
Если ЗначениеЗаполнено(Выборка.КоличествоЭлементовКолекцииНаПоток) Тогда
СтруктураПараметров.ПараметрыИнициализации.ПараметрыОбработкиКоллекции.КоличествоЭлементовКолекцииНаПоток = Выборка.КоличествоЭлементовКолекцииНаПоток;
КонецЕсли;
Если ЗначениеЗаполнено(Выборка.КоэффициентКратностиОчередиПотоковКПотокам) Тогда
СтруктураПараметров.ПараметрыИнициализации.КоэффициентКратностиОчередиПотоковКПотокам = Выборка.КоэффициентКратностиОчередиПотоковКПотокам;
КонецЕсли;
Если ЗначениеЗаполнено(Выборка.ПределКоличествоПопытокОбработатьОбъект) Тогда
СтруктураПараметров.ПараметрыИнициализации.ПределКоличествоПопытокОбработатьОбъект = Выборка.ПределКоличествоПопытокОбработатьОбъект;
КонецЕсли;
СтруктураПараметров.ПараметрыОбщие.Активно = Истина;
СтруктураПараметров.ПараметрыОбщие.Вставить("МинимальноеКоличествоКоллекции",Макс(Выборка.МинимальноеКоличествоКоллекции,1));
КонецЕсли;
КонецПроцедуры
Показать
Если ИмяСобытия = "ПриПолученииРесурсов" Тогда //Поток
ОтветСобытия = ПриПолученииРесурсов(пПараметрыСобытия);
//Сообщение = Новый СообщениеПользователю;
//Сообщение.Текст = "Ресурс получен";
//Сообщение.Сообщить();
ИначеЕсли ИмяСобытия = "ПриОбработкеДействияПотока" Тогда //Поток
СтруктураДанных = пПараметрыСобытия.СтруктураДанных;
ПараметрыДляОбъекта = СтруктураДанных.ПараметрыДляОбъекта;
РегистрыСведений.векОчередьДляПереобеспечения.ОбработатьДокумент(ПараметрыДляОбъекта.Период, СтруктураДанных.ОбрабатываемыйОбъект);
Показать
Функция ПриПолученииРесурсов(пПараметрыСобытия)
СтруктураДанных = пПараметрыСобытия.СтруктураДанных;
ОбрабатываемыйОбъект = СтруктураДанных.ОбрабатываемыйОбъект;
ТабличнаяЧастьДокумента = ПолучитьТабличнуюЧастьДокумента(ОбрабатываемыйОбъект);
МассивРесурсов = Новый Массив;
МассивРесурса = Новый Массив;
МассивРесурса.Добавить(векПолучитьЗначениеРеквизита(ОбрабатываемыйОбъект,"Склад"));
Для каждого СтрокаТЧД из ТабличнаяЧастьДокумента Цикл
МассивРесурса.Добавить(СтрокаТЧД.Номенклатура);
КонецЦикла;
МассивРесурсов.Добавить(МассивРесурса);
Возврат МассивРесурсов;
КонецФункции
(40) Подскажите, пожалуйста, я правильно понимаю, что ОбработатьОбъект() только для ссылочных объектов? То есть если например необходимо в многопотоке обрабатывать очередь из регистра сведений, то придется использовать либо метод "ДополнитьКоллекцию", либо "ОбработатьКоллекцию"? Хотелось задействовать расчет ресурсов для построения графов, чтобы при работе фоновых заданий добавлять в коллекцию новые события, появляющиеся в очереди (новые записи регистра сведений). Почитал, посмотрел, но вот с этими вопросами не доразобрался.
Хотелось задействовать расчет ресурсов для построения графов, чтобы при работе фоновых заданий добавлять в коллекцию новые события, появляющиеся в очереди (новые записи регистра сведений)
Добрый день!
Если не сложно можете расписать задачу, чуть подробнее (желательно в личку, чтоб тут не засорять), возможно удастся предложить решение
(62) Добрый день! Возможно получить вариант решения аналогичной по сути проблемы? Пытаюсь передать в ОбработатьОбъект() не записанный ДокументОбъект, хочется также задействовать расчет ресурсов.
(87) [IS-QUOTE] Добрый день! Просьба описать ваш случай более детально. Возможно у Вас есть особенности. Кроме того прошлое решение было почти 2 года назад - результатов сходу уже не вспомнить.
(88) Из таблицы значений построчно создаем документ Корректировка долга, заполняем его данными и проводим, вот собственно и всё. В день +- 5000 документов. Сейчас на проведение каждого уходит 4-5 сек. Возможны взаимоблокировки, т.к. Контрагент и Договор могут повторяться. Конфигурация Бухгалтерия предприятия, редакция 3.0 (3.0.120.14) 1С:Предприятие 8.3 (8.3.20.1710) -MS SQL
1. В ОбработатьОбъект() можно передавать как "объект" все что угодно, главное чтоб объект передавался 1 раз. В исключительной ситуации можно передать УникальныйИдентивикатор, а все параметры для создания объекта передать 3им параметром (ПараметрыДляОбъекта) в виде структуры.
2. В событии "ПриРасчетеРесурсов" для каждого объекта собираете ресурсы, мне кажется достаточно только договоров (контрагент не обязательно), но при этом надо понимать, что, возможно, договоров в одном документе может быть несколько, а значит в массиве ресурсов будет несколько ресурсов к одному объекту.
3. В событии "ПриОбработкеПотоком" Создаем/проводим документы.
4. При необходимости в событии "ПриОбработкеОшибки" описываем алгоритм при не возможности создать документ, например вывод сообщения со ссылкой на документ и остановка МП от дальнейшей работы
5. При необходимости в событии "ПриОбработкеПропуска" Выводим информацию если по объекту не удалось рассчитать ресурсы.
6. При необходимости в событии "ПриОбработкеРезультата" обрабатываем успешную обработку объекта.
Добрый день, получаю бесконечный цикл, соответственно не может завершиться менеджер потоков, что я могу упускать?
Функция ДождатьсяОстановкиМенеджераПотоков(пСтруктураПараметров) Экспорт
...
Пока ПолучитьЗначениеХранилищаОбщихНастроек(РазрезМенеджеров, "ИдФЗМенеджераПотоков") <> Неопределено Цикл
Слипп(0.1);
КонецЦикла;
...
(51) Выложить данный функционал хочу уже давно, вот только времени все "в кучу" собрать пока не получается :(
Очень надеюсь, что до ИС все же получиться провернуть данный вариант.
Вы в версии 2.0.7 разделили модуль на 4 шт, а обработку с примерами забыли обновить. В ней теперь передача мутабельного на сервер происходит. Например, тут:
НоваяКоллекция = мпМенеджерПотоков.ДополнитьКоллекциюОбъектов(СтруктураПараметров, Коллекция);
Подскажите, как средствами МП организовать индикацию хода выполнения? Вот прямо на форму, из которой выполнен запуск МП в несколько потоков, выводить либо общий по всем потокам процент выполнения, либо обновлять индикатор. Потупил какое-то время в документацию, но не увидел подходящего. Подробно не прошу объяснять, просто идею. Спасибо!
(56) Добрый день.
На текущий момент данного функционала не предусмотрено. Есть идеи по реализации, но пока руки не доходят :(
Так же один из клиентов МП - данный функционал реализовал (https://infostart.ru/profile/890948/). Думаю он не откажет в помощи.
В руководстве написано, что взаимодействие с платформой 1С:Предприятие для Windows. При использовании Linux, какие необходимо внести изменения в Менеджер потоков?
Версия 2.1.0.1 (скачивали с другого аккаунта, ppeskov)
Есть ли какие то ограничения по месту вызова мпОсновнаяПрограммаВызовСервера.ИнициализироватьМенеджерПотоков(ПараметрыМП); ?
При размещении данного кода в модуле объекта в предопределенной процедуре ОбработкаПроведения инициализации не происходит, падает с ошибкой
Ошибка при выполнении обработчика - 'ОбработкаПроведения'
по причине:
{ОбщийМодуль.мпОбщееСервер.Модуль(133)}: "Менеджер потоков" - прервал выполнение
ВызватьИсключение ТекстСообщения;
ясности не прибавляет. Перенесли пока функционал в команду формы, работает без нареканий.
"Исторически так сложилось" что на основании табличной части документа в процессе проведения происходят "волшебные вещи", распараллеливание вашей конфигурацией творит в этом плане чудеса, хотелось бы все-таки попробовать перенести распараллеливание в проведение, не сильно при этом меняя текущую логику
(63) Добрый день!
Правильно ли я понял, что вы хотите распараллелить проведение документа?
Боюсь не получиться, по крайне мере я не смог найти решение. Первое с чем Вы можете столкнуться при такой реализации – это взаимоблокировки, т.к. фоновые задания (потоки) генерируют другие транзакции.
На прошлой конференции ИС-2019, я общался с Дмитрием Дудиным (https://infostart.ru/profile/198214/) (он обмолвился, что знает, как распараллелить проведение). В кулуарах он мне пытался объяснить, но я его объяснение не осилил ☹, может вам повезет больше 😊.
По поводу ограничений… Ограничений быть не должно ни каких сверх того, что накладывает сама платформа 1С.
По поводу сообщения об ошибке. Что написано в журнале регистрации?
По поводу «волшебные вещи» и «чудеса» - о чем речь?
Фоновое задание. Запуск
Фоновое задание. Ошибка выполнения
{ОбщийМодуль.мпОбщееСервер.Модуль(133)}: Общий модуль "" не найден.
Сеанс. Завершение
Ошибка выполнения
{ОбщийМодуль.мпОбщееСервер.Модуль(133)}: "Менеджер потоков" - прервал выполнение
Нет, мы не планируем распараллеливать проведение документа. Данный документ у нас по сути выполняет функции Бизнес процесса, выполняет определенные действия над объектами, ссылки которых содержатся в табличной части в определенной последовательности, а флаг "проведён" устанавливается после успешного выполнения всех действий. И хотя данный функционал находится в обработке проведения, движений он не формирует, лишь свидетельствует об успешности. Для того чтобы избежать взаимоблокировок в процессе обработки объектов и используем вашу обработку, с табличной частью 3000 строк и более она дает отличные результаты ускорение в 3-4 раза, но пока не получается "последняя миля", место вызова
Причина в следующем: В момент проведения активна транзакция (самого документа), в механизме обмена данными между «Основной программой» / «Менеджером потоков» и «Потоками» участвует «ХранилищеОбщихНастроек», для согласованности обмена между ФЗ, чтение из хранилища идет в транзакции. Тут и происходит проблема, при проведении происходит инициализация параметров и их передача в ФЗ менеджера потоков, но он их прочитать из хранилища не может, т.к. на стороне «Основной программы» - обработки проведения транзакция не завершена.
Решение (кратко - см. скрины): инициализацию и запуск менеджера потоков необходимо выполнить в отдельном ФЗ.
Надеюсь такое решение не вписывается в "не сильно при этом меняя текущую логику"
(67) Пробую реализовать данный вариант - столкнулся с тем, что при данном варианте теряется часть "Обратной связи". Например перестают отрабатывать Сообщения пользователю в фоновом задании. В соответствующем окошке тишина. При вызове Функции ПриОбработкеПотоком(пПараметрыСобытия) если перед возвратом указываем
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = СтрШаблон("Создан возврат %1",Документы.ВозвратТоваровОтКлиента.ПолучитьСсылку(Новый УникальныйИдентификатор(XmlСтрокаНаВозврат)));
Сообщение.Сообщить();
Возврат Документы.ВозвратТоваровОтКлиента.ПолучитьСсылку(Новый УникальныйИдентификатор(XmlСтрокаНаВозврат));
То строка появляется только при "обычном" вызове из формы, если мы выносим многопоточность в отдельное фоновое задание из транзакции проведения, то в окне сообщений тишина.
Я правильно понимаю, что пока единственный вариант контроля за результатом в режиме запуска в транзакции проведения, это всё-таки использование коллекций с автосборкой и возвратом результатов работы в удобной форме, и мириться со взаимоблокировками ресурсов, не используя обработку объекта и функцию ПриРасчетеРесурсов? Или всё таки есть способ увидеть результаты по всем ФЗ после обработки всех потоков обработки объектов?
(70) Думаю что можно, но надо проверить. Необходимо реализовать по аналогии с текущим механизмом.
Ваши сообщения выводятся, но только в фоновом задании в котором происходит инициализация МП.
В приведенном выше примере показано помещение во временное хранилище "КоллекцияПриемник", туда можно поместить структура с 2 значениями, "КоллекцияПриемник" и "СообщениеПользователю"
СообщениеПользователю получить как описано в функции мпПотокиСервер.ПолучитьСообщениеДляПользователя()
И уже в своей программе после ожидания ФЗ получить структуру и вывести сообщение.
Надеюсь смог донести мысль. Если возникнут проблемы - постараюсь на днях накидать пример :)
(79) Что за база в которой выходит сообщение? Это база из поставки 1Cv8.cf, или это Ваша база куда Вы загрузили "Поставку"?
Работоспособность демо примеров просьба проверять на пустой базе из поставки 1Cv8.cf. При загрузки поставки в свою базу, часть объектов по умолчанию не переносятся (именно демо модули)
(80) УПП 1.3, перенес все объекты из 1Cv8.cf, что самое интересное, демо примеры (обработки) отрабатывают, с точно таким же кодом инициализации...не отрабатывает вызов в модуле "ЗаполнениеДокументов", буду копать
Первый день, пока не особо разобрался, что делаю не так, вызывается метод "ИнициализироватьМенеджерПотоков" и фоновые задания "бесконечно" (около часа наблюдал) бегают по процедурам и модулям, т.е. до точки останова дело даже не доходит, не выходит из процедуры этого метода...
(82)Внедрил успешно подсистему, проблемный, долгий расчет себестоимости в УПП ускорен ~10 раз, очень ценный продукт, большое спасибо за труд, автор очень отзывчивый, всегда был рад помочь, за что отдельное спасибо, однозначно забрал данный продукт в свой арсенал, пригодится на крупных проектах, уже есть варианты, где буду дальше применять
(95) Добрый день!
Думаю не стоит заморачиваться с 2.0.7 - мониторинг там был до жути простой и не функциональный.
Сейчас идет разработка новой версии. Мониторинг там будет включен. В принципе он уже был реализован в версии 2.1.1, но увиденные проблемы с помощью мониторинга привели к разработке новой версии МП. Разработка идет как обычно, когда время находиться, но теперь более интенсивно чем ранее. Так же будет расширена функциональность, которой оказалось очень не хватало в МП в методе "ОбработатьОбъект".
В общем ждите новостей :)