1с выполнить код в фоне
Фоновые задания 1С, примеры работы и параллельного запуска
В рамках выполнения проекта столкнулся с интересной задачей ускорения загрузки данных из других информационных баз. Задача загрузки данных предполагала выполнение к внешней базе несвязанных между собой запросов, результаты которых помещаются в одну таблицу значений. Когда на оптимизацию запроса рука уже не поднималась, приступил к ускорению загрузки с помощью распараллеливания процессов. Отмечу, что элементы кода в данном посте приведены для клиент-серверного варианта и укрупнено для общего понимания подхода.
Что у нас в 1с Предприятии 8.2 имеется для распараллеливания & это фоновые задачи. Метод, который будет вызываться в фоновой задаче, должен быть прописан в серверном общем модуле и быть экспортным. Естественно нам понадобиться в фоновую задачу передавать и забирать значения.
В моем случае передача значений в фоновую задачу происходила через параметры. Метод ЗагрузитьИзВИБ имеет два параметра это ВходнойПараметр и АдресВХранилище. ВходнойПараметр это структура, в которую сгружаются все данные, необходимые для проведения загрузки. АдресВХранилище это адрес во временном хранилище, по которому будет передан результат загрузки. Сам код метода фонового задания выглядит так:
Зачем нам в фоновую задачу передавать адрес во временном хранилище. Наша фоновая задача должна куда-то положить результат, причем так чтобы мы знали где его потом взять.
Для того чтобы запустить фоновые задачи выполняется следующий код:
Перед запуском фоновой задачи через ФоновыеЗадания.Выполнить() мы формируем массив параметров. Значения из массива параметров переходят в метод фонового задания в качестве параметров. В МассивЗапущенныхЗаданий хранятся все фоновые задачи, которые мы запустили. Теперь надо подождать их ожидания.
ФоновыеЗадания.ОжидатьЗавершения(МассивЗапущенныхЗаданий);
После того как все задачи были завершены, можем приступить к получению из них данных. Для этого мы проходим по всем адресам в хранилище, которые хранятся в массиве МассивАдресовВХранилище. После получения результата фонового задания перегоняем его в общую таблицу.
Вопрос определения оптимального количества потоков выходит за рамки данного поста. А после получения некоторых результатов на рабочих данных пока что выходит и за рамки моего сознания . Но если у вас есть идеи как посчитать нужное количество потоков, пишите в комментариях, с радостью почитаю.
В данной статье приведен пример работы с фоновыми заданиями, как в 1С производится запуск фоновых заданий, каким образом можно получить список заданий при помощи метода «ПолучитьФоновыеЗадания()». Итак, данный метод возвращает нам некоторый массив. Посмотрим что же он содержит.
Cразу оговорюсь, что приведенный пример разрабатывался в клиент-серверном варианте работы базы.
На рисунке представленном выше видно содержимое данного массива.
Обратите внимание на поле «Состояние». Оно содержит информацию о том, успешно ли было выполнено запущенное фоновое задание или же оно еще выполняется.
Также там содержится информация о неудачном выполнении задания. Еще этот массив содержит информацию о ключах, уникальных идентификаторах, наименовании фоновых заданий. Информация о выполняющихся и выполненных заданиях хранится в информационной базе, но есть ограничение на количество хранимых записей в таблице. Это количество составляет порядка 1000 записей. То есть при добавлении новых элементов старые удаляются. Также задание удаляется из таблицы если оно было выполнено более суток назад.
Давайте также рассмотрим работу с фоновыми заданиями на примере метода «ПолучитьФоновыеЗадания()». В данном методе есть возможность установить отбор на получаемые записи. То есть в качестве параметра метода нам нужно передать структуру.
Структура может содержать поля: Уникальный идентификатор, Ключ, Состояние, Начало, Конец, Наименование, ИмяМетода, РегламентноеЗадание.
Например, если бы нам нужны были только выполняющиеся задания мы бы накладывали отбор с именем элемента структуры «Состояние» и значением бы мы указали системное перечисление «СостояниеФоновогоЗадания» в состояние активно. Итак, для начала необходимо добиться того, чтобы в демонстрационной базе появились записи о выполнении фоновых заданий 1С.
Для реализации примера сделаем следующее:
1. Создадим общий модуль «ОбработчикиФоновыхЗаданий», выполняемый на сервере.
И добавим в него следующий код:
Процедура ПроизвестиФоновоеВычисление ( Параметр ) Экспорт
2. Создадим обработку, разместим на форме кнопку «Выполнить задание в фоне» и в процедуре обработки события нажатия на кнопку добавим код:
Описание вызываемой процедуры:
Теперь запустим 1С в режиме предприятия и запустим выполнение фонового задания.
Готово. Этими действиями мы добились того, что в нашей демонстрационной базе появились записи о выполнении фоновых заданий 1С и теперь можно продемонстрировать пример получения их массива, содержащегося в нашей базе.
Добавим на форму еще одну кнопку «Получить фоновые задания». Напишем в процедуре обработки нажания следующий код:
Текст процедуры на сервере:
Запустим 1С на выполнение и нажмем кнопку «Получить фоновые задания».
В окно сообщений выведутся наименования выполняющихся и выполненных в 1С фоновых заданий с наименованием «Тестовое задание 2», так как мы сделали отбор именно по этому наименованию. Укажем в параметрах отбора наименование «Тестовое задание» и получим массив содержащий элементы данного задания.
Надеюсь приведенный выше пример дал вам некоторое понятие о механизме фоновых заданиях реализованном в системе 1С. Более детально ознакомиться со всеми тонкостями вы можете во встроенном синтакс-помошнике 1С.
Скачать базу с примером работы с фоновым заданием вы можете тут
Фоновые задания в 1С 8.3
Фоновые задания
Иногда требуется выполнить какую-нибудь длительную операцию без блокирования интерфейса. То есть пользователь нажал кнопку, запустилась какая-нибудь длительная процедура, а в этом время пользователь может делать что-нибудь другое в программе. Для этого можно использовать механизм фоновых заданий.
Фоновые задания запускаются асинхронно (без ожидания завершения), в отдельном потоке. Фоновые задания можно запустить только на сервере. Для примера, представим что есть некий список электронных адресов, на который нужно выполнить рассылку по электронной почте. В списке может быть много адресов, да и отправка одного письма выполняется какое-то время. Поэтому хотелось бы запустить рассылку и продолжить дальше работать с программой.
Чтобы запустить фоновое задание используется метод Выполнить менеджера фоновых заданий. Первым параметром передается имя общего модуля и имя метода. Указанный метод должен находиться в общем модуле и быть экспортным.
В результате будет запущено фоновое задание, которое выполнит метод ВыполнитьРассылку из общего модуля МодульФоновыхЗаданий. Во время выполнения фонового задания интерфейс пользователя не будет заблокирован.
Если сейчас трижды запустить одно фоновое задание, то оно будет запущено три раза и три раза выполнит одно и то же действие. Чтобы избежать повторного запуска фонового задания, если оно уже было запущено можно использовать Ключ фонового задания. Ключ передается третьим параметром в метод Выполнить:
В результате при первом выполнении данного кода будет запущено фоновое задание с ключом «Рассылка». Если не дождавшись выполнения текущего фонового задания попробовать запустить его еще раз, то будет выброшено исключение «Задание с таким значением ключа уже выполняется». Если указать другое значение ключа, то оба фоновых задания будут выполняться одновременно.
Если у фоновых заданий с одним значением ключа не совпадают методы для выполнения, то такие задания могут быть запущены одновременно.
Стоит отметить, что в качестве метода для фонового задания можно использовать как процедуру, так и функцию. Возвращаемый результат функции будет проигнорирован. В качестве метода фонового задания нельзя использовать методы глобальных общих модулей.
Параметры фонового задания
При запуске фонового задания можно передать параметры в метод общего модуля. Например, добавим в процедуру ВыполнитьРассылку два параметра:
При запуске фонового задания вторым параметром нужно перадать массив параметров. Первый элемент массива будет передан в первый параметр, второй — во второй и т.д.
Если количество параметров не будет совпадать, то фоновое задание не будет выполнено.
Фоновые задания в файловом и клиент-серверном варианте
Механизм выполнения фоновых заданий отличается в файловом и клиент-серверном варианте.
В файловом варианте фоновые задания выполняются на том клиентском приложении, которое его запустило. Одновременно может выполняться только одно фоновое задание, остальные фоновые задания встают в очередь.
В клиент-серверном варианте фоновые задания выполняются планировщиком заданий, который находится в менеджере кластера. Планировщик заданий подбирает наименее загруженный рабочий процесс сервера 1С и выполняет фоновое задание на нем.
И в файловом и клиент-серверном варианте фоновое задание это отдельный системный сеанс, который выполняется от имени того пользователя, кто создал задание.
Фоновое задание с ожиданием результата
Если требуется дождаться результата выполнения фонового задания, то можно воспользоваться тем, что метод Выполнить возвращает объект Фоновое задание. А у этого объекта есть метод ОжидатьЗавершенияВыполнения, который остановит поток выполнения, пока не изменится состояние фонового задания. Фоновое задание может быть в четырех состояниях:
После изменения состояния фонового задания метод ОжидатьЗавершенияВыполнения вернет обновленное фоновое задание, у которого можно анализировать свойство Состояние, чтобы узнать результат выполнения:
Метод Выполнить вернул фоновое задание, состояние которого было равно Активно. Состояние автоматически не обновляется. Для проверки изменения состояния фонового задания нужно заново получить фоновое задание. В данном примере оно было получено методом ОжидатьЗавершенияВыполнения.
Пауза через фоновое задание
В метод ОжидатьЗавершенияВыполнения параметром можно передать количество секунд. Выполнение кода продолжится или по истечении этого времени или сразу после изменения состояния фонового задания. Можно воспользоваться данным методом для возможности оставить выполнение кода на указанное количество секунд. В общий модуль добавим следующую процедуру:
Параметром принимаем количество секунд для паузы, затем определяем чей это сеанс. Если клиентский, то запускаем фоновое задание и ждем его завершения. Если это сеанс фонового задания, то просто ждем его завершения.
Вызов паузы на 5 секунд:
Преимущество такого метода в том, что на время паузы не загружается процессор.
Оповещение о выполнении фонового задания
Иногда требуется не просто запустить выполнение фонового задания, а оповестить пользователя о результатах выполнения. Для этого можно использовать следующий алгоритм действий:
Здесь был использован метод ПодключитьОбработчикОжидания, который вызывает процедуру, указанную в первом параметре через время, указанное во втором параметре. Затем вызов процедуры был отменен через метод ОтключитьОбработчикОжидания.
Отмена выполнения фонового задания
Для отмены фонового задания можно использовать метод Отменить самого фонового задания:
Сообщения из фонового задания
Фоновое задание выполняется на сервере, поэтому если в нем использовать сообщения пользователю, то их никто не увидит. Однако у фонового задания есть метод ПолучитьСообщенияПользователю, который позволяет получить все сообщения из фонового задания. Для примера добавим в общий модуль следующую процедуру:
Выполним ее через фонового задание с получением всех сообщений и выведем полученные сообщения на экран:
Через сообщения можно организовать получение прогресса выполнения фонового задания. Добавим в общий модуль следующие процедуры:
И запустим фоновое задание на выполнение, с периодическим получением сообщений:
В результате в процессе выполнения фонового задания можно будет увидеть окно состояния с прогрессом выполнения:
Многопоточность через фоновые задания
С помощью фоновых заданий можно выполнить какую-то обработку в несколько потоков. Например, нужно во всем справочнике товаров увеличить цену на 10%. Можно разбить все товары на несколько частей и каждую часть обработать в отдельном потоке:
Здесь мы использовали метод ОжидатьЗавершения, но уже не у самого фонового задания, а у менеджера фоновых заданий. Параметром передали массив тех фоновых заданий, завершение которых нужно дождаться. У менеджера фоновых заданий тоже есть метод ОжидатьЗавершенияВыполнения, в который помимо массива заданий можно передать таймаут, аналогично одноименному методу у фонового задания. Даже если в методе ОжидатьЗавершенияВыполнения не указывать таймаут, то он в любом случае вернет массив всех обновленных фоновых заданий, после изменения статуса хотя бы у одного задания. Так как нам нужно дождаться завершения всех заданий, то был использован метод ОжидатьЗавершения.
Стоит отметить, что в одном фоновом задании можно запустить другое фоновое задание. То есть можно было запустить одно фоновое задание, в нем распараллелить выполнение на четыре фоновых задания, дождаться их выполнения и оповестить пользователя о завершении.
В силу ограничений выполнения фоновых заданий в файловом варианте многопоточную обработку данных можно реализовать только в клиент-серверном варианте.
Получить фоновые задания
Метод ПолучитьФоновыеЗадания позволяет получить список всех фоновых заданий, сохраненных в базе данных. Выполненные фоновые задания хранятся в течении суток, но не более 1000 заданий. Соответственно метод ПолучитьФоновыеЗадания вернет как текущие фоновые задания (выполняются в данный момент), так и завершившиеся в течении суток задания.
Фоновое выполнение кода в 1С — это просто
Не буду растекаться мыслью по дереву и тянуть кота за все известные места, так как надеюсь, все согласятся, что фоновое выполнение это хорошо. Есть простой путь запускать любой код в фоне. Специалисты скорее всего такой способ используют, но что-то в инете я описания не встретил, решил выложить.
Перво-наперво создаем общий модуль с именем например «ФоновоеВыполнение» с галкой «Сервер». Добавим туда пару процедур:
Теперь для выполнения когда в любой момент мы можем поместить любую процедуру в текстовую переменную:
И вызывать ее выполнение:
Related Posts
21 Comments
…А как узнать-то что всё завершилось?
(2)Там есть процедура проверяющая результат выполнения, которая подключается через обработчик ожидания.
Вроде вагон подобных идей на ИС уже реализован в обработках и подсистемах по распараллеливанию через фоновые задания. Ну и про выполнение(формирование) например отчетов в фоне тоже вагон информации (особенно много появилось информации когда управляемые формы появились). Плохо гуглили мне кажется)))
А для многопоточности можно ещё завернуть в цикл.
Пример: Изменение / Удаление чего-то делать в потоках быстрее.
А как насчет отладки? Или получение результата выполнения?
Давайте завернем все что можно «Выполнить», это же 1С, можно делать все что хочешь…
Или все-же стоит пробовать реализовать лучшие мировые практики программирования?
(5) возможно, не закапывался сильно, т.к. искал не для использования, просто просмотрел насколько тема актуальная и что про нее написано.
(7) Для получения результатов выполнения мы возвращаем Уникальный идентификатор, который можем использовать для тестирования. В комментариях даже есть способ как это сделать. С отладкой все так же, запускаем процедуру, ставим точку останова и автоматическое подключение фоновых заданий
Я за использование БСП и запуск фонового задания из модуля внешней обработки, без модификации основной конфигурации.
(10) Это правильно, я сам против модификации стандартных конфигураций, тут скорее идея, которая может быть использована при работе. В любом случае реализация будет зависеть от задачи.
А вообще примеров с ФЗ в интернете много, странно, что не нашли ничего…
Лениво проверять, но ИМХО в процедуре
Для Каждого ТекПараметр Из ПараметрыВыполнения Цикл
Плохо, что до сих пор разработчики 1С не добавили возможность запускать фоновые задания прямо из внешних обработок, открываемых интерактивно через меню Файл. Могли бы добавить возможность передавать в качестве параметра фоновому заданию — сам объект обработки, для копирования его в сеанс фонового задания и исполнения в нем скомпилированного кода.
Кроме того контроль прогресса фонового задания на стороне клиента надо выносить в отдельный поток вызывающий сервер для получения прогресса, а то сейчас видно, как меняется иконка курсора мышки на иконку ожидания при каждом периодическом опросе прогресса и добавляет задержку в работе пользователя.
(13) ТекПараметр.Ключ берется из ПараметрыВыполнения, это второй параметр
Что полезного даёт эта статья? Знание того что в 1с есть фоновые задания и есть метод выполнить. Надоело тратить время на чтение статей описывающих синтаксис-помощник.
(16)Согласен с Вами. Меня очень удивило, что автор не нашел статей по данному вопросу…
Вот отличная статья на инфостарте про ФЗ и БСП:
Ну, а про Выполнить и того статей больше…
Не понимаю в чем проблема? Может когда искал интернет не работал…
(14) для получения информации со стороны сервера — реализована система взаимодействия. Оповещение вызывает СЕРВЕР.
А вот запуск в фоне без доработки — дааа — давно пора убирать костыли со стороны 1С
(17) Отличная статья, спасибо за ссылку! Повторюсь, что искал я поверхностно, и у меня тут только практическая часть для использования «здесь и сейчас», это для тех кому срочно нужно, и у кого нет времени плотно погрузится и изучить тему всесторонне.
(18)Которая с сентября только в корпоративной версии платформы за кучу денег…
(9) Возвращать-то надо УИД ФЗ, а не его ключ, в который положен произвольный УИД.
Потому как в общем случае кому-то может захотеться запускать ФЗ с произвольным (задаваемым извне) ключом.
1С фоновое задание позволяет нам производить какие-либо вычисления в системе незаметно для пользователя, то есть в фоне. Более того данный механизм позволяет нам распараллелить процесс вычисления. Распараллелить мы можем даже процедуру, которая будет выполняться. Для этого наше фоновое задание должно запускать еще несколько фоновых заданий. В этом случае процессы распараллеливаются и, если у нас многопроцессорная, многоядерная система, наш алгоритм будет работать эффективно. После запуска нескольких процессов мы можем сказать системе, что необходимо дождаться окончания выполнения этих процессов для того, чтобы потом каким-то образом свести результат.
К примеру, в типовых конфигурациях, в то время как пользователь работает, происходит выполнение различного рода сервисных фоновых заданий. Об этом может свидетельствовать записи журнала регистрации, в котором фиксируется факт выполнения таких действий. Причем на работу пользователя это никак не влияет, он просто их не замечает.
В идеале фоновое задание реализуется в варианте клиент-сервер, в этом случае вся нагрузка переходит на сервер. Что касается файлового варианта, то работа фонового задания возможна, но она имеет некоторые особенности.
Вот что выдаст система если не учесть эти особенности, и запустить фоновое задание в файловом варианте информационной базы.
1С фоновое задание имеет некоторые ограничения. Поскольку оно выполняется на стороне сервера, то нет возможности интерактивной работы с пользователем. К примеру нельзя вывести сообщение, ну и вообще какую-то информацию. Все эти данные нужно сохранять в рамках информационной базы и дальше каким-то образом обрабатывать.
Обратившись к синтакс-помощнику можно получить более детальные сведения о фоновых заданиях 1С. Здесь следует отметить, что это объект исключительно программный и он никак не сохраняется в базе данных. То есть мы создаем экземпляр класса, инициализируем свойства и запускаем его на выполнение.
Какие же средства мы имеем для управления фоновыми заданиями? Этим средством является объект метаданных«МенеджерФоновыхЗадания». У этого объекта есть метод «Выполнить», с помощью этого метода, как раз и запускается фоновое задание.
Возвращаемым значением является объект «ФоновоеЗадание», содержащий текущее имя метода, текущий ключ и еще несколько свойств и методов. Одним из таких методов является метод «ОжидатьЗавершения». Его задачей является то, что мы может указать системе, чтобы ничего не производилось пока не будет завершено фоновое задание.
Приведем пример работы с фоновыми заданиями 1С. Сначала создадим простой алгоритм, который будет ненадолго загружать систему 1С таким образом, чтобы мы ничего не могли в это время делать.
Для этого:
1. Создадим общий модуль «ОбработчикиФоновыхЗаданий», который будет компилироваться на стороне сервера;
2. Опишем в нем экспортную процедуру «ПроизветиФоновоеВычисление(Параметр)», которая принимает один параметр строкового типа;
3. Далее создадим внешнюю обработку и в событии нажатия на кнопку поместим код, запускающий наш алгоритм;
Готово. Теперь при запуске обработки и нажатии на кнопку происходит подвисание системы на несколько секунд, в процессе которого ничего нельзя сделать. Это как раз то, что нам и нужно было сделать.
Теперь обеспечим произведение этих вычислений в фоне, то есть чтобы фоновое задание 1С 8.2, 8.3 выполнялось, но нам не мешало.
Для этого:
1. В обработке, в событии нажатия кнопки пропишем следующий код.
Готово. Теперь можем проверять. Перезапускаем нашу обработку нажимаем кнопку, система не подвисает и мы работаем беспрепятственно.
Кстати, убедиться в том, что 1С фоновое задание работало можно посмотрев в записи журнала регистрации. В этих записях фиксируется когда производился запуск фонового задания.
Приведенный выше пример показывает, как работает фоновое задание 1С 8.2, 8.3. То, каким полезным оно может быть в разработке ваших алгоритмов.
Скачать базу с примером вы можете тут