1с передача параметров в фоновое задание
Когда-то давно передо мной была поставлена задача добавить в документ определенный реквизит и доработать процедуру заполнения табличных частей этого документа с отбором по этому реквизиту.
Казалось бы, задача для опытного (да и не очень опытного) 1С-ника простая, нужно всего лишь добавить реквизит, вывести его на форму, найти процедуру заполнения и доработать её.
Однако, в моем случае процедура заполнения документа вызывалась через типовой механизм "Длительные операции" или по-простому через механизм "Фоновых заданий", т.е. по нажатию на кнопку "Заполнить", программа заполняла структуру параметров и запускала фоновое задание из модуля менеджера документа с этими параметрами. Далее, вызывались нужные процедуры по заполнению таблиц документа. Однако, в эти процедуры передавалась не вся структура параметров (куда я мог поместить и свой в том числе), а лишь некоторые из них. Плюс к этому одним вызовом нужной процедуры дело не ограничивалось, до того, как параметры доходили до нужной процедуры заполнения они преодолевали тернистый путь из последовательного вызова 7-8 типовых процедур.
Иными словами, для такой "простейшей" задачи нужно было перелопачивать программный код (прописывать во все вызовы процедур наш дополнительный параметр), что потом бы неизбежно привело к проблемам с обновлениями.
Решено было создать простой регистр сведений, который был назван "ДополнительныеПараметрыПроцедурИФункций":
В результате чего алгоритм решения вышеописанной задачи свелся к следующему:
- Перед заполнением установить значение нужного нам параметра, записав его значение в регистр сведений
- В процедуре заполнения прочитать значение параметра из регистра
- Непосредственно доработать саму процедуру с учетом нашего параметра
Почему я для данного случая не использовал:
- Константы - не подходят для данного случая, так как параметры могут быть различными (у константы должно быть уникальное имя) и не постоянными (зависят, например, от значения реквизита конкретного документа)
- Параметры сеанса - данные параметры уникальны только в разрезе конкретного сеанса. Т.е. на примере выше, когда "поднимается" фоновое задание у него уже "свои" значения параметров сеанса
Процедуры чтения/записи значения параметров:
Данный регистр можно использовать не только так, как описано выше, но и как, например, хранение периодически изменяемых параметров, ради которых не хочется создавать в конфигурации константы.
В приложении к публикации находится простейшая конфигурация, демонстрирующая описанный выше механизм.
Лучше придумать другой алгоритм "диспетчерзиации" задач между запущенными заданиями. Так, чтобы не требовалось гонять половину базы в оперативной памяти (а это и происходит при передаче параметров фонового задания).
(3) Этот вариант оч. долго согласовывать, и скорее всего не одобрят, плюс доступы на SQL выпрашивать. И не совсем понятно как объектные сущности в таблице значений разложить в таблице SQL много шаманства по моему будет
(8) формально он у тебя есть - ты же в базу ходишь как-то
>И не совсем понятно как объектные сущности в таблице значений разложить в таблице SQL много шаманства по моему будет
мы не в курсе накой черт тебе 12 лямов записей
(7) Если РЗ=ФЗ, то думал об этом, но к сожалению в моей задаче это не сработает
(15) Передается из одной процедуры выполняемом в серверном общем модуле, в фоновое задание, которое то же на сервере выполняется.
(16) Сериализация-десериализация ТЗ способны устроить кошмар любой системе.
>Как эта ТЗ формируется? Очень сложно?
запускают чего-то типа расчет себестоимости - и привет
тз ->хз. можно еще попробовать хз в строку внутреннюю.
либо тз с хз и в временный файл.
было не так давно в одной отраслевой упп.
модуль проведение документа.
внутри 2-го обход ТЧ и набивание ТЗ построчно.
теперь простая арифметика:
ТЗ = 10 000 000 строк
клиент "думает" до 2 Гб и падает
что делает клиент? звонит во франь, консультант франя заходит по rdp на сервак и (о чудо!) проводит документ. За 10 минут. Сервак 64-бит. А значит 3,5 Гб на клиента скребя ложкой по дну ему хватает.
какой вывод сделал франь?
купите 64-бит сервер 1с.
(17) Запись движений в базу (сколько строк столько и движений) :)
+(33) например, в фоновое передавать только организацию, подразделение и там группу какой-нить номенклатуры, а таблицу оборотов (предположим, что речь про обороты) получать из базы уже там
(33) нет, так как запрос делается по движениям в базе, которые потом либо меняются либо удаляются (после запроса), если один фон начнет менять движения, а второй начнет их только читать перед подготовкой ТЗ, то в итоге они будут работать с разными таблицами значений
(35) Пусть фоны читают ТЗ и ждут, пока все флаги в служебном регистре сведений не установятся в "Можно писать"
(37) управляемый режим давно уже включен, "ДЛЯ ИЗМЕНЕНИЯ" игнорится, наверное можно управляемую блокировку установить, только по таймауту тож легко вылететь
(36) Наверное в регистр в ресурс с типом ХранилищеЗначения проще положить саму табличку, спасиб за идею с регистром, ща буду пробовать
(38) При положении в ХЗ пойдет сериализация в XDTO + кодирование в base64, которое, я боюсь, выполнено через опу..
При извлечении из ХЗ пойдет обратный процесс.
21-й век на дворе, а все возитесь с таблицами значений?
Пригласите специалиста.
(29) нет, зачем франч предложил купить 64бит сервер, если он уже есть? на который консультант зашел через рдп.
(41) Пишется и читается вне транзакции, блокировки вообще не сработают, плюс (если делать в транзакции) большая вероятность таймаута
(31) распараллеливается запись одного набора?
и в наборе 12 миллионов строк?
что-то я не очень понял.
странно что все пытаются придумать что делать с тз, вместо того, чтобы удостовериться в том, что в принципе выбрана правильная методика решения задачи.
(35) разбей данные на не пересекающиеся куски и читай-пиши, сколько угодно и когда угодно
(51) Мне то они не нужны, типовой расчет себестоимости в упп 1.3, по методологии расчета вопрос тож не ко мне, не я ее утверждал.
(40) Да, не получилось в ХранилищеЗначения в рег. сведений поместить, 200 тыс. записей легко прошли сек. за 20, а на 5 млн отвалилось по ошибке потока (
(58) Вы пытаетесь сделать какое-то "еврейское" распараллеливание - думаю, что ничего у Вас не выйдет. Предполагаемая модель для распределения задач по "потокам" - убога и нежизнеспособна.
Вместо того, чтобы пытаться с помощью "молотка и такой-то матери" как-то передать ТЗ "потоку" - гораздо перспективней будет подойти к вопросу с другой стороны.
Проанализировать алгоритм, определить на какие атомарные операции его можно разбить - и уже от этого "плясать"
(59) Угумс. Типы, не имеющие XDTO-сериализации - прекрасно помещаются в хранилище значения. Есть и обратные примеры - когда тип помещается в хранилище, но не имеет XDTO-сериализации.
Исследования методом "научного тыка" показали, что, помещение в хранилище значения - эквивалентно ЗначениеВСтрокуВнутр(), а не XDTO-сериализации.
(60) Все такие умные, что ППЦ.
Ну, разбей хотя бы алгоритм удаления движений по нескольку регистров на поток - заипешься код писать, а потом (самое главное) ошибки ловить. Это примитив.
А мы тут про расчет себестоимости.
(62) Многопоточность это вообще сложно.
(64) И что? Есть типы, которые ее не имеют - но в хранилище помещаются. И наоборот, есть типы которые не помещаются в хранилище, но пишутся в XDTO
(61)
Исследования методом "научного тыка" показали.
(66) Вкратце - перебирались почти все типы встроенного языка (вплоть до ОбъектМетаданных, ИсторияРаботыПользователей, РасширенноеИмяXML - и прочего безобразия).
Для каждого типа делалась попытка:
(68) Масштабно, епта.
Результаты опубликуй.
ТЗ В XDTO есть? Нет? А если найду?!
(69) Если найду - опубликую.
Еще выяснилось, что просто ЗаписатьXML() - который метод глобального контекста - тоже сильно разнится с СериализаторXDTO.ЗаписатьXML().
ТЗ в XDTO есть :) Но это не значит, что помещение в хранилище значения - есть XDTO
(70)
ЗаписатьXML() - который метод глобального контекста - тоже сильно разнится с СериализаторXDTO.ЗаписатьXML().
Подозреваю, что просто ЗаписатьXML() от 8.0 остался, пока XDTO не было.
(0) Я через выгружал в текстовый файл и булками загружал во временную таблицу.
(71) Ты случайно с ЗаписатьXDTO не путаешь?
(68) Дааа, ты чертовски прав..
1) Создал справочник с реквизитом ХЗ.
Простите за кодировку, было лениво морочиться.
(76) Так там не один кусок памяти, а набор объектов (строки ТЗ, колонки) содержащих друг на друга, наверно. Может стоит указать объект СжатиеДанных?
(76) Кстати а как насчет использования ЗаписьFastInfoset
(76) Вот тут я конечно тот еще басист - но что-то мне подсказывает, что если просто сохранять кусок памяти - то его потом будет оооочень сложно прочитать следующей версией, когда в плюсовом классе будет изменен состав членов.
Например, в той же Java - если сделать implements Serializable и не реализовывать свои writeObject и readObject - то именно так и получится. А если реализовывать writeObject и readObject - то это уже не будет "просто кусок памяти".
В которую будут преобразованы двоичные данные :)
(74)
Вы забыли указать степень сжатия при создании хранилища.
(83) protobuf, как и json - всего-лишь форматы. Ничего нового в такое понятие как сериализация они не приносят.
К тому же, даже из вашей ссылки на вики:
> По замыслу разработчиков сначала должна быть описана
> структура данных, которая затем компилируется в классы,
Т.е. опять-таки нет речи о том, чтобы просто взять кусок оперативной памяти и зафигачить в файл (а потом просто прочитать из файла).
На основании объекта класса строится DTO-представление, которое уже и пишется файл.
Не лучше все движения запихнуть во временную таблицу с полем порядковый номер. И забирать уже из временной по условию (от 1 до милиона) - первый поток, от милиона+1 до двух милионов - второй поток и тд.
(86) Для этого всего-лишь нужно умудриться передать в другой сеанс менеджер временных таблиц)
(86) Каким же образом из разных сеансов (фоновых заданий) получать временную таблицу созданную в родительском сеансе?
(82) Я не сомневался в тебе. Сжатие данных скорее всего сожмет эту строку deflate-ом.
(85) Если это массив структур то можно взять и кусок памяти, так как они храняться все в одном непрерывном куске.
Что касается объектов, то они разбросаны по всей памяти.
Таблица типизирована, то можно записывать как в DBF для данных с определенным размером либо указывая размер данных в первых байтах например для строк.
Либо записывать в аналог иерархической бд
(93) Я не соглашусь с тобой.
Имхается мне, что все объекты в 1С - связные списки (даже массивы и структуры) - нет падения скорости вставки на больших объемах.
Мегазадача. а если попробовать как-то получать из разных сеансов адрес ячеек в ОЗУ, занятых исходной таблицей (которую инициировал родительский сеанс)?
(95) Аххх, если бы узнать адреса объектов 1С. мммм, какие возможности, но. Мечты. мечты.Можно создавать локальные и глобальные временные таблицы. Локальные временные таблицы видимы только во время текущего сеанса, а глобальные — во всех сеансах. Временные таблицы не подлежат секционированию.
Инструкции SQL могут обращаться к временной таблице по заданному в инструкции CREATE TABLE значению аргумента table_name, например:
В рамках выполнения проекта столкнулся с интересной задачей ускорения загрузки данных из других информационных баз. Задача загрузки данных предполагала выполнение к внешней базе несвязанных между собой запросов, результаты которых помещаются в одну таблицу значений. Когда на оптимизацию запроса рука уже не поднималась, приступил к ускорению загрузки с помощью распараллеливания процессов. Отмечу, что элементы кода в данном посте приведены для клиент-серверного варианта и укрупнено для общего понимания подхода.
Что у нас в 1с Предприятии 8.2 имеется для распараллеливания & это фоновые задачи. Метод, который будет вызываться в фоновой задаче, должен быть прописан в серверном общем модуле и быть экспортным. Естественно нам понадобиться в фоновую задачу передавать и забирать значения.
Зачем нам в фоновую задачу передавать адрес во временном хранилище. Наша фоновая задача должна куда-то положить результат, причем так чтобы мы знали где его потом взять.
Для того чтобы запустить фоновые задачи выполняется следующий код:
Перед запуском фоновой задачи через ФоновыеЗадания.Выполнить() мы формируем массив параметров. Значения из массива параметров переходят в метод фонового задания в качестве параметров. В МассивЗапущенныхЗаданий хранятся все фоновые задачи, которые мы запустили. Теперь надо подождать их ожидания.
ФоновыеЗадания.ОжидатьЗавершения(МассивЗапущенныхЗаданий);
После того как все задачи были завершены, можем приступить к получению из них данных. Для этого мы проходим по всем адресам в хранилище, которые хранятся в массиве МассивАдресовВХранилище. После получения результата фонового задания перегоняем его в общую таблицу.
Вопрос определения оптимального количества потоков выходит за рамки данного поста. А после получения некоторых результатов на рабочих данных пока что выходит и за рамки моего сознания . Но если у вас есть идеи как посчитать нужное количество потоков, пишите в комментариях, с радостью почитаю.
В рамках выполнения проекта столкнулся с интересной задачей ускорения загрузки данных из других информационных баз. Задача загрузки данных предполагала выполнение к внешней базе несвязанных между собой запросов, результаты которых помещаются в одну таблицу значений. Когда на оптимизацию запроса рука уже не поднималась, приступил к ускорению загрузки с помощью распараллеливания процессов. Отмечу, что элементы кода в данном посте приведены для клиент-серверного варианта и укрупнено для общего понимания подхода.
Что у нас в 1с Предприятии 8.2 имеется для распараллеливания & это фоновые задачи. Метод, который будет вызываться в фоновой задаче, должен быть прописан в серверном общем модуле и быть экспортным. Естественно нам понадобиться в фоновую задачу передавать и забирать значения.
Зачем нам в фоновую задачу передавать адрес во временном хранилище. Наша фоновая задача должна куда-то положить результат, причем так чтобы мы знали где его потом взять.
Для того чтобы запустить фоновые задачи выполняется следующий код:
Перед запуском фоновой задачи через ФоновыеЗадания.Выполнить() мы формируем массив параметров. Значения из массива параметров переходят в метод фонового задания в качестве параметров. В МассивЗапущенныхЗаданий хранятся все фоновые задачи, которые мы запустили. Теперь надо подождать их ожидания.
ФоновыеЗадания.ОжидатьЗавершения(МассивЗапущенныхЗаданий);
После того как все задачи были завершены, можем приступить к получению из них данных. Для этого мы проходим по всем адресам в хранилище, которые хранятся в массиве МассивАдресовВХранилище. После получения результата фонового задания перегоняем его в общую таблицу.
Вопрос определения оптимального количества потоков выходит за рамки данного поста. А после получения некоторых результатов на рабочих данных пока что выходит и за рамки моего сознания . Но если у вас есть идеи как посчитать нужное количество потоков, пишите в комментариях, с радостью почитаю.
Читайте также: