gifts2017

Асинхронная концепция программирования в «1С:Предприятие 8» или выполнение программного кода «в фоне»

Опубликовал Знать 1С Хочу (AXIOMLAB24) в раздел Программирование - Практика программирования

Как правило, в реальных задачах оказывается недопустимым длительное выполнение обработчика события, поскольку при этом программа не может реагировать на другие события - блокируется пользовательский интерфейс.
В данной статье рассмотрены следующие вопросы:
1. Концепция асинхронного программирования
2. Фоновые задания в «1С:Предприятие 8»
3. Пример асинхронного выполнения длительных серверных операций с помощью фонового задания
4. Пример асинхронного выполнения длительных серверных операций с помощью фонового задания с использованием БСП.

Концепция асинхронного программирования

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

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

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

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

 

При синхронном выполнении у приложения есть только один поток. С помощью асинхронной модели программирования вы можете запускать множество параллельных потоков и во время их выполнения реагировать на новые действия пользователя. После того как n-поток выполнен, вы отображаете результат на экран.

 

Фоновые задания в «1С:Предприятие 8»

В «1С:Предприятие 8» фоновые задания предназначены для выполнения прикладных задач асинхронно. Они могут порождать дочерние фоновые задания, например, для распараллеливания сложных вычислений по различным рабочим серверам кластера в клиент-серверном варианте работы.

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

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

 

Клиент-серверный вариант

В клиент-серверном варианте планированием выполнения заданий занимается планировщик заданий, который физически располагается в менеджере кластера.

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

Файловый вариант

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

Раньше для автоматического выполнения заданий требовалось запускать отдельный, дополнительный сеанс «1С:Предприятия», используемый в качестве планировщика заданий. И в этом сеансе нужно было периодически выполнять метод встроенного языка ВыполнитьОбработкуЗаданий(). Такой подход был довольно громоздким, неудобным и сильно ограничивал использование фоновых и регламентных заданий в файловом варианте работы.

Теперь всё стало гораздо проще. Если стартует тонкий или толстый клиент, а также если у веб-сервера есть клиентские соединения, то в каждом из этих приложений автоматически запускается еще один поток с подключением к базе данных. Эти потоки занимаются тем, что выполняют фоновые и регламентные задания.

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

 

Очевидный минус 1С фоновых заданий: поскольку они выполняются на стороне сервера, то нет возможности интерактивной работы с пользователем (к примеру, нельзя вывести сообщение или какую-нибудь другую информацию; все эти данные нужно сохранять в рамках информационной базы и дальше каким-то образом обрабатывать).

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

 

Пример асинхронного выполнения кода в «1С:Предприятие 8»

«Писать программы, в которых результат вызова функции приходит неизвестно когда - куда сложнее, чем обычные. Вложенные вызовы, обработка ошибок, контроль над происходящим - все усложняется», - так скажут только те, кто не умеет правильно пользоваться возможностями платформы, но не мы!

Продемонстрируем всю простоту и изящество асинхронного выполнения кода в «1С:Предприятие 8»!

Шаг 1. Создадим новую ИБ для разработки конфигурации

Шаг 2. В конфигурации добавим общий модуль «АсинхронныеОбработчики»

Почему мы добавили общий модуль? Тут все просто: для выполнения асинхронных операций в «1С:Предприяте 8» применяются фоновые задания, у которых имеется свой менеджер - «МенеджерФоновыхЗадания». У этого объекта есть метод «Выполнить», с помощью которого как раз и запускается фоновое задание.

Обратимся к синтакс-помощнику.

 

Таким образом, нам понадобится общий модуль.

 

 

Шаг 3.  В общем модуле «АиснхронныеОбработчики» добавим экспортную процедуру НашаДлительнаяОперация()

Процедура НашаДлительнаяОперация(Длительность) Экспорт
	// Имитация продолжительного действия (Длительность сек.).
		ДатаНачалаОперации = ТекущаяДата();
		Пока ТекущаяДата() - ДатаНачалаОперации < Длительность Цикл
	КонецЦикла;
КонецПроцедуры

Шаг 4. Добавляем в конфигурацию обработку «АсинхроннаяКонцепцияПрограммирования» (можно создать внешнюю обработку)

 

На форму добавляем один реквизит:

- Длительность (Число)

и две команды

- ВыполнитьДлительнуюОперацию;

- ВыполнитьДлительнуюОперациюАсинхронно.

Шаг 5.  Согласно синтакс-помощнику заполняем модуль формы

&НаКлиенте
Процедура ВыполнитьДлительнуюОперацию(Команда)
	ВыполнитьДлительнуюОперациюНаСервере();
КонецПроцедуры

&НаСервере
Процедура ВыполнитьДлительнуюОперациюНаСервере()
	АсинхронныеОбработчики.НашаДлительнаяОперация(Длительность);
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьДлительнуюОперациюАсинхронно(Команда)
	ВыполнитьДлительнуюОперациюАсинхронноНаСервере();
КонецПроцедуры

&НаСервере
Процедура ВыполнитьДлительнуюОперациюАсинхронноНаСервере()

	Параметры = Новый Массив;
	Параметры.Добавить(Длительность);
	
	ФоновыеЗадания.Выполнить("АсинхронныеОбработчики.НашаДлительнаяОперация", 
		Параметры, Новый УникальныйИдентификатор, "Пример асинхронной концепции программирования");	
	
КонецПроцедуры
 

Шаг 6. Запускаем и проверяем!

Результат:

- если мы нажимаем на кнопку «Выполнить длительную операцию», то пользовательский интерфейс на «Длительность» секунд блокируется;

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

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

 

Отладить программный код, который выполняется в «фоне» мы можем, если в параметрах отладки установим соответствующее свойство.

 

Пример асинхронного выполнения кода в «1С:Предприятие 8» с использование БСП

Пример реализации асинхронной концепции программирования в «1С:Предприятие 8» в БСП рассмотрим на примере обработки «Текущие дела».

 

 

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

 

Проанализируем программный код формы.

Событие формы «ПриСозданииНаСервере» вызывает процедуру «ЗапуститьФоновоеЗадание» - это то, что нам и нужно. 

 

Не отвлекаясь на нюансы, анализируем данную процедуру

 

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

И Что же дальше? А дальше нам необходимо отловить момент выполнения задания.

Для этого разработчики применяют метод ПодключитьОбработчикОжидания(<ИмяПроцедуры>, <Интервал>, <Однократно>).

В подключаемой процедуре Подключаемый_ПроверитьВыполнениеЗадания() разработчики вызывают функцию ЗаданиеВыполнено(ИдентификаторЗадания)


Данная функция по идентификатору проверяет выполнения фонового задания.

Необходимо отметить, что в БСП разработаны общие модули поддержки работы длительных серверных операций.

 

Таким образом, асинхронная концепция программирования в «1С:Предприятие 8» незначительно увеличивает трудоемкость решения задач для разработчика, но заметно улучшает функциональность программы с точки зрения пользователя.

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Олег Кострицын (recon) 04.04.15 13:08
Отличная статья! Но у фоновых заданий есть и подводные камни, связанные с ошибками (или фичами?) платформы. В частности 1С не контролирует расход процессорного времени при выполнении фонового задания и десяток фоновых заданий, выполняющих какой то "тяжелый" расчет, могут запросто положить сервер на лопатки. Выход - перенос менеджера фоновых заданий на другой сервер (доступно с платформы 8.3), а значит фоновые задания будут выполняться на выделенном сервере. Возможно в новых релизах что то поменялось
Ну и периодически на сервере может зависнуть процесс фонового задания. 1С хоть и реализовала метод аварийного завершения фонового процесса, но на самом деле он всего лишь посылает команду завершения, не завершая принудительно процесс. Приходится контролировать зависшие процессы периодически через консоль сервера.
2. Егор Иванов (Infactum) 05.04.15 12:05
Конечно на безрыбье и рак рыба, но называть это все асинхронным программированием будет не совсем корректно. Для реализации полноценного асинхронного программирования нужна либо нормальная работа с обратными вызовами, либо Promise/Deferred. Очень рекомендую по смотреть в сторону node.js + callback/promise или C# + async/await, чтобы понять, как именно все это должно работать. По факту сейчас за 1С просто стыдно :(
brr; 7OH; Kuzja_R; cefew; nSpirit2; perpleks; Жолтокнижниг; +7 3 Ответить 1
3. Евгений Сосна (pumbaE) 05.04.15 13:35
(2) Ну так используйте Показатьоповещение, бесконечный loop и подключитьобработчик ожидания. Превращать в callback ад, код ради "стыдно" не имеет смысла.
В том же питоне, попытались не реализовывать сразу весь ужас callback и не превращать в код в спагети.
4. Егор Иванов (Infactum) 05.04.15 14:00
(3) pumbaE, в питоне есть asyncio. Я на callback модели и не настаивал, специально привел несколько примеров.
И к слову о JS и "callback hell" - это проблема исключительно начинающих программистов. Использование библиотек типа node-async или отказ от обратных вызовов в пользу обещаний решает все это на корню.
5. Евгений Сосна (pumbaE) 05.04.15 14:21
(4) в типовой поставке 1с нет ни тестирования, ни документации кода, как получить работающий код при малейшем изменении одного из обещаний?
Уже сейчас можно с трудом отладить модель подписок в БСП, пока инструментов нет для нормальной поддержки кода.
6. Валерий К (klinval) 06.04.15 09:21
&НаСервере
Процедура ВыполнитьДлительнуюОперациюАсинхронноНаСервере()

    Параметры = Новый Массив;
    Параметры.Добавить();
    
    ФоновыеЗадания.Выполнить("АсинхронныеОбработчики.НашаДлительнаяОперация", 
        Параметры, Новый УникальныйИдентификатор, "Пример асинхронной концепции программирования");    
    
КонецПроцедуры
...Показать Скрыть

Вы случайно не забыли в параметрах передать длительность?
AXIOMLAB24; +1 Ответить 1
7. AxiomLab (AXIOMLAB24) 06.04.15 09:45
(6) klinval, Спасибо! Подправил.
8. г. Казань Рустем Гумеров (Rustig) 09.04.15 12:07
(0) проект интересный!

....а как мы жили раньше без этого?!.....
я учил бухгалтеров так: запускаете один сеанс бухгалтерии, запускаете формирование ОСВ,
открываете второй сеанс бухгалтерии и продолжаете работу во втором сеансе....

задачи другого рода, когда бухгалтер нажимает на кнопку, и следующий процесс чересчур длительный я решал таким образом: например отправку счета на оплату в БП 1.6 - создал регистр сведений "Очередь отправки", куда записывалось электронное письмо. В параллельном сеансе под пользователем "Электронка" все собранные письма начинали отправляться по очереди, не нагружая сеанс 1С у бухгалтера...

9. Иван Устьянцев (nSpirit2) 09.04.15 12:20
Много много букав совсем не о чем :)
К сожалению пока вся концепция 1с завязана на том что клиентские приложение само отслеживает выполнилось фоновое задание или нет.
Обилие описания плюсов о том что пользовательский интерфейс не блокируется по большей части преувеличение удобности этого для пользователя. Мы не завешиваем окно пользователя но не факт ему нужно работать пока не закончиться длительная операция. Отслеживание работы пользователя по большей части показывает, что выполнение отчета в фоне не как не помогает пользователю работать так как он ожидает результат. Для моей базы это примерно 70 процентов. Так что речь о оставлении возможности интерактивной работы пользователя по большей части надумана. Так как любая длительная операция которая необходима пользователю по большей части не требует не блокировки интерфейса это скорее удобность работы так как пользователи по большей части не многозначны и ожидают результата своих действий перед выполнением следующей задачи. Основная удобность всех фоновых процессов к сожалению сводиться к возможности незаметно для пользователя обновлять часть видимой ему информации. Либо перенос в них задач результат выполнения которых пользователь не ожидает.

Что относительно описания в БСП. Я думал будет больше функции из модулей <color #FF6347>ДлительныеОперации</>*.
Такие функции как СообщитьПрогресс и ПрочитатьПрогресс к сожалению не нашли отражения в примере хотя именно для длительных операций они весьма интересны. Что интересно. C помощью него можно выполнять не только экспотрные процедуры но и команды отчетов и обработок что значительно удобней чем строковых адресов в функции.

Простите но статья по большей части не о чем. Ждем детального продолжения.

(5) pumbaE, То что вы по прежнему кушайте кактус совсем не значит что другие тоже его едят. Есть и инструменты для тестирования и инструменты для документирования. А относительно спагети. Вы пробуйте написать паралельно вычисление на фоновых заданиях вам callback счастьем покажется.

(4) Infactum, К слову а JS в 1с со всей этой концепцией фоновых вычислений по большей части не хватает возможности помещения в переменные ссылок на функции для дальнейшего их использования.
10. Евгений Сосна (pumbaE) 09.04.15 12:24
Есть и инструменты для тестирования и инструменты для документирования
поделитесь хотя-бы названиями.
11. Иван Устьянцев (nSpirit2) 09.04.15 12:35
(10) pumbaE,
https://github.com/xDrivenDevelopment/xUnitFor1C ну для тестирования вот вам ссылка. Посмотрите) А то куда ведет ссылка ответ на вопрос про документацию.
shalimski; JohnyDeath; kuntashov; Pr-Mex; lustin; +5 Ответить 3
12. Евгений Сосна (pumbaE) 09.04.15 12:40
(11) дайте догадаюсь документацию в wiki?
13. Иван Устьянцев (nSpirit2) 09.04.15 12:46
(12) pumbaE, Ну в моем случае это git + некоторые скрипты для извлечения комментариев из хода.
14. Евгений Сосна (pumbaE) 09.04.15 12:54
(13) не поделитесь скриптами по документированию и опытом работы с xUnitfor1c?
Какие режимы работы тестируете (управляемые формы, обычные формы)?
Используете ли 8.3.5 кнопку нажималку для тестового случая?
Как часто запускаете тесты? Автоматизировали ли CI в виде какого-либо сервиса сборки? Автоматизировали ли CD для обновления production базы?
Какие затраты на написание тестов были вначале, какие сейчас?

Мне было-бы очень интересно услышать ответы на эти вопросы.
pbazeliuk; Rustig; +2 Ответить 2
15. AxiomLab (AXIOMLAB24) 09.04.15 13:01
(9) nSpirit2, благодарю за детальный комментарий!
По пунктам,
п.1
Простите но статья по большей части не о чем.

Нет предела совершенству - будем стараться, будем работать над собой!

п.2
Отслеживание работы пользователя по большей части показывает, что выполнение отчета в фоне не как не помогает пользователю работать так как он ожидает результат. Для моей базы это примерно 70 процентов.

Асинхронная концепция вписывается и в Ваш сценарий - тот, кто привык сидеть и ждать пусть так и продолжает. Но все же, на мой взгляд, современная тенденция развития личности, как профессионала своего дела, требует от него многозадачности. А если основной инструмент работы (ПП "1С:Предприятие") заблокирован хоть на несколько секунд, то как должен к нему относится пользователь?

п.3
Что относительно описания в БСП. Я думал будет больше функции из модулей <color #FF6347>ДлительныеОперации</>*

Главной задачей статьи является попытка передать КОНЦЕПЦИЮ асинхронного программирования, но с небольшими и понятными примерами в "1С:Предприятие".

Ждем детального продолжения.

Если тема заинтересует достаточное количество специалистов, то продолжение следует!
16. Алексей Лустин (lustin) 10.04.15 12:27
(11) nSpirit2, ;-) сделал мой день ;-)
CSiER; nofx; pbazeliuk; kuntashov; +4 Ответить 2
17. Алексей Лустин (lustin) 10.04.15 12:43
(0) Ну это всё конечно хорошо, но раз уж тема актуальна и поднята, но это не наш метод - нет у нас доверия стабильности БСП, потому что нет тестов на эту функциональность, как верно заметили в (5)

А что же тогда наш метод ? Вот вам пример вчера публикации на Хабре:

1. Исходная публикация http://habrahabr.ru/post/255387/
2. Репозиторий на github https://github.com/wizi4d/TaskManagerFor1C
3. Кстати *внезапно* подсистема накрыта тестами https://github.com/wizi4d/TaskManagerFor1C/tree/master/%D0%A2%D0%B5%D1%81%D­1%82%D1%8B
18. Иван Устьянцев (nSpirit2) 10.04.15 12:52
(16) lustin, Нуу я все таки надеюсь что эта часть будет сильно популярна в среде 1С разработчиков что бы было меньше объяснять новым разработчикам.
(17) lustin, Я описания на github прочитал. Идея конечно отличная не подскажите к быстро будет развиваться функциональность. К несчастью функционал БСП она пока не покрывает есть ли план развития ?
19. Алексей Лустин (lustin) 10.04.15 13:00
20. Алексей Лустин (lustin) 10.04.15 13:13
(18) nSpirit2

1. по развитию надо спрашивать у https://plus.google.com/+ЕвгенийПавлюк - не могу определенно сказать какие у него дальнейшие планы. Сейчас насколько я понимаю была основная цель - поделиться подсистемой.

2.
что бы было меньше объяснять новым разработчикам.
тут вот какое дело, только без обид - потому что это было весело...

мы также поступаем - советуем всем использовать подходы и инструментарий. Тот же xUnit или https://github.com/silverbulleters/vanessa-behavoir, но блин... вы дали ссылку на инструментарий одному из авторов ;-) https://github.com/pumbaEO
21. Иван Устьянцев (nSpirit2) 10.04.15 13:19
(20) Неожиданные высказывания для разработчика :D Теперь и я ржу :D
22. Евгений Сосна (pumbaE) 10.04.15 14:39
(21) ну основное мое замечание касалось "типовой"(поставки, типового функционала от 1с).
23. Кирилл Бондаренко (karapuzzzz) 10.04.15 16:55
От себя добавлю как можно передавать параметры и ловить результат.
Для начала создаем временное хранилище:
АдресВХранилище = ПоместитьВоВременноеХранилище(Неопределено);

Потом создаем массив, в который заносим адрес в хранилище и остальные параметры:
НаборПараметров = Новый Массив;
НаборПараметров.Добавить(АдресВХранилище);
НаборПараметров.Добавить(Параметр1);
НаборПараметров.Добавить(Параметр2);
НаборПараметров.Добавить(Параметр3);
...Показать Скрыть

Если идет распараллеливание задания, то создается массив заданий и массив адресов в хранилище.
В самом задании результат помещаем в хранилище:
ПоместитьВоВременноеХранилище(Результат, АдресВХранилище);

После того как словили факт окончания выполнения задания можно обработать результат. Для этого получаем результат из хранилища и делаем что хотим с этим:
Результат = ПолучитьИзВременногоХранилища(АдресВХранилище)

24. Евгений Мартыненков (JohnyDeath) 10.04.15 17:29
(11) Весело наблюдать за тем, как советуют поучиться инструменту одному из основных разработчиков этого инструмента )))
u_n_k_n_o_w_n; nofx; artbear; tormozit; kuntashov; Evil Beaver; karapuzzzz; +7 Ответить 2
25. Андрей Овсянкин (Evil Beaver) 10.04.15 18:11
(24) JohnyDeath, Ну это же круто, это признание!
JohnyDeath; kuntashov; +2 Ответить 1
26. Евгений Сосна (pumbaE) 10.04.15 19:34
(25), (24), (16) тролли. Я, наоборот, рад тому, что кто-то другой знает и использует данный инструмент.

p.s.:
Мне все таки интересен ответ на (14) вопрос, хоть частичный.
h00k; artbear; nSpirit2; JohnyDeath; kuntashov; +5 Ответить
27. Иван Устьянцев (nSpirit2) 11.04.15 10:27
(14) pumbaE, xUnitfor1c познакомились примерно в июле 2014. Случайно наткнулся в Гугле. С тем учетом что наша компания по факту занимается разработкой и продажей ПО которое сами и пишем (не 1с ). Cсобственно к разработке на 1с для внутренних нужд применяются те же требования. Используем для CI что то отдаленно напоминающее TeamCity. С возможностью автоматического тестирования и выкладки при условии динамического обновления. В части тестов интерфейсов после полного перехода на Управляемые формы в конце июня используем xUnitfor1c.

Ну относительно затрат сложный вопрос. С начала было тяжело были специальные люди которые писали тесты для интерфейсов. Но вообщем оно однозначно того стоит. Теперь в части маленьких изменений используем TDD.

Относительно документирования используем большую часть возможностей которые дает Git. В текущей ситуации пытаемся понять насколько возможно использовать стандартный git-flow для 1с не храня бинарники *.cf на всякий случай.
Это если совсем коротко.
28. Артур Аюханов (artbear) 12.05.15 17:13
Что-то я эту тему пропустил.
И упоминание "моей прелести" xUnitFor1C также :)

(27) А используете именно Gui/интерфейсные тесты в xUnitFor1C (через кнопко-нажималку) или обычные тесты в УФ для xUnitFor1C также юзаете?
29. Ярослав Радкевич (WKBAPKA) 25.09.15 09:17
Статья довольно таки интересная.
Для решения некоторых задач оч. даже полезная
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа