Фоновая обработка больших данных в 1С с прогресс баром
Пару лет назад уже сталкивался с подобной задачей (Фоновая обработка больших данных в 1С). Чуть погуглил, что изменилось за это время. А фактически ничего. До сих пор для того чтобы показать обычный прогресс бар, приходится использовать велосипеды. Временные хранилища, для того чтобы передать в клиента результат работы фоновой функции/процедуры как нельзя было использовать, так и сейчас нельзя. Прогресс бар, как нельзя было использовать без костылей…так и сейчас нельзя. Ну я конечно не смотрел что в БСП, т.к. зачастую приходится делать дописки где БСП или нет, или она древняя
Общая «шаблонная» схема использования фонового выполнения функций в 1С можно организаовать следующим образом:
- Запускаем фоновое задание
- На клиенте запускаем периодическое задание которое отлавливает вывод «сообщить» на сервере
- В фоновом задании при помощи «сообщить» выводим всякую служебную информацию. Если нужно в «клиент» передать данные — записываем временный файл в формате например json, и имя его, опять же при помощи «Сообщить» передаём на клиент.
- По окончании фонового задания, закрываем выполнение периодического задания
Запуск фонового задания:
1 2 3 4 5 6 7 8 9 10 11 12 |
&НаКлиенте ... ЗапускФоновойЗадачи(); ПодключитьОбработчикОжидания("ИндикаторВыполненияЗагрузки",1,ложь); ... &НаСервере Процедура ЗапускФоновойЗадачи() МассивПараметров = Новый Массив; МассивПараметров.Добавить(параметры); ФЗ = ФоновыеЗадания.Выполнить("СК_ГР_ДлительныеОперации.СпарситьИсходныеДанныеНаСервер",МассивПараметров); ЭтаФорма.ФоновоеИдентификатор = ФЗ.УникальныйИдентификатор; КонецПроцедуры |
Процедура или функция фонового задания обязательно должна находиться в общем модуле:
1 2 3 4 5 6 7 8 9 10 |
Функция СпарситьИсходныеДанныеНаСервер(параметры) экспорт; ... Сообщить("Выполнено 10%"); .... Сообщить("Выполнено 100%"); ИмяФайла=ПолучитьИмяВременногоФайла("json"); Текст = Новый ЗаписьТекста(ГдеИскать+ИмяФайла, КодировкаТекста.UTF8); Текст.Записать(json_str); Сообщить("Результат:"+ИмяФайла); ... |
Периодическая проверка и «отлов» серверного вывода «Сообщить»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
&НаКлиенте Процедура ИндикаторВыполненияЗагрузки() Экспорт пр=ОпроситьФоновые(); если пр<>неопределено тогда объект.ИндВыполнения=пр; Состояние("Выполнено "+пр); конецесли; КонецПроцедуры &НаКлиенте Процедура ИндикаторВыполненияЗагрузки() Экспорт пр=ОпроситьФоновые(); если пр<>неопределено тогда объект.ИндВыполнения=пр; Состояние("Выполнено "+пр); конецесли; КонецПроцедуры &НаСервере Функция ПолучитьСообщенияФЗ(ФЗ, Состояние = Неопределено, УдалятьСообщения = Ложь) Экспорт Если Состояние = Неопределено Тогда Состояние = ФЗ.Состояние; КонецЕсли; МассивСообщений = Новый Массив; Сообщения = ФЗ.ПолучитьСообщенияПользователю(УдалятьСообщения); Если Сообщения <> Неопределено Тогда Для Каждого Сообщение Из Сообщения Цикл МассивСообщений.Добавить(Сообщение.Текст); КонецЦикла; КонецЕсли; Возврат МассивСообщений; КонецФункции &НаСервере Функция ОпроситьФоновые() прог=неопределено; ФЗ = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ЭтаФорма.ФоновоеИдентификатор); если ФЗ=Неопределено тогда ОтключитьОбработчикОжидания("ИндикаторВыполненияЗагрузки"); возврат ложь; конецесли; ФСообщения=ПолучитьСообщенияФЗ(ФЗ,,истина); Если ФСообщения.Количество() > 0 Тогда Для Каждого Сообщение Из ФСообщения Цикл Сообщить(Сообщение); если найти(Сообщение,"%")>0 тогда прог=Число(СтрЗаменить(СтрЗаменить(Сообщение,"Выполнено ",""),"%","")); конецесли; если найти(Сообщение,"Результат:")>0 тогда ИмяФайла=СтрЗаменить(Сообщение,"Результат:",""); Текст = Новый ЧтениеТекста(КаталогВременныхФайлов()+ИмяФайла, КодировкаТекста.UTF8); СтрокаJson = JsonВСтруктуру(Текст.Прочитать()); ОтключитьОбработчикОжидания("ИндикаторВыполненияЗагрузки"); конецесли; КонецЦикла; КонецЕсли; возврат прог; КонецФункции |
В результате будет что-то вроде: