Фоновая обработка больших данных в 1С с прогресс баром
Пару лет назад уже сталкивался с подобной задачей (Фоновая обработка больших данных в 1С). Чуть погуглил, что изменилось за это время. А фактически ничего. До сих пор для того чтобы показать обычный прогресс бар, приходится использовать велосипеды. Временные хранилища, для того чтобы передать в клиента результат работы фоновой функции/процедуры как нельзя было использовать, так и сейчас нельзя. Прогресс бар, как нельзя было использовать без костылей…так и сейчас нельзя. Ну я конечно не смотрел что в БСП, т.к. зачастую приходится делать дописки где БСП или нет, или она древняя
Общая «шаблонная» схема использования фонового выполнения функций в 1С можно организаовать следующим образом:
- Запускаем фоновое задание
- На клиенте запускаем периодическое задание которое отлавливает вывод «сообщить» на сервере
- В фоновом задании при помощи «сообщить» выводим всякую служебную информацию. Если нужно в «клиент» передать данные — записываем временный файл в формате например json, и имя его, опять же при помощи «Сообщить» передаём на клиент.
- По окончании фонового задания, закрываем выполнение периодического задания
Запуск фонового задания:
&НаКлиенте
...
ЗапускФоновойЗадачи();
ПодключитьОбработчикОжидания("ИндикаторВыполненияЗагрузки",1,ложь);
...
&НаСервере
Процедура ЗапускФоновойЗадачи()
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(параметры);
ФЗ = ФоновыеЗадания.Выполнить("СК_ГР_ДлительныеОперации.СпарситьИсходныеДанныеНаСервер",МассивПараметров);
ЭтаФорма.ФоновоеИдентификатор = ФЗ.УникальныйИдентификатор;
КонецПроцедуры
Процедура или функция фонового задания обязательно должна находиться в общем модуле:
Функция СпарситьИсходныеДанныеНаСервер(параметры) экспорт;
...
Сообщить("Выполнено 10%");
....
Сообщить("Выполнено 100%");
ИмяФайла=ПолучитьИмяВременногоФайла("json");
Текст = Новый ЗаписьТекста(ГдеИскать+ИмяФайла, КодировкаТекста.UTF8);
Текст.Записать(json_str);
Сообщить("Результат:"+ИмяФайла);
...
Периодическая проверка и «отлов» серверного вывода «Сообщить»:
&НаКлиенте
Процедура ИндикаторВыполненияЗагрузки() Экспорт
пр=ОпроситьФоновые();
если пр<>неопределено тогда
объект.ИндВыполнения=пр;
Состояние("Выполнено "+пр);
конецесли;
КонецПроцедуры
&НаКлиенте
Процедура ИндикаторВыполненияЗагрузки() Экспорт
пр=ОпроситьФоновые();
если пр<>неопределено тогда
объект.ИндВыполнения=пр;
Состояние("Выполнено "+пр);
конецесли;
КонецПроцедуры
&НаСервере
Функция ПолучитьСообщенияФЗ(ФЗ, Состояние = Неопределено, УдалятьСообщения = Ложь) Экспорт
Если Состояние = Неопределено Тогда
Состояние = ФЗ.Состояние;
КонецЕсли;
МассивСообщений = Новый Массив;
Сообщения = ФЗ.ПолучитьСообщенияПользователю(УдалятьСообщения);
Если Сообщения <> Неопределено Тогда
Для Каждого Сообщение Из Сообщения Цикл
МассивСообщений.Добавить(Сообщение.Текст);
КонецЦикла;
КонецЕсли;
Возврат МассивСообщений;
КонецФункции
&НаСервере
Функция ОпроситьФоновые()
прог=неопределено;
ФЗ = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ЭтаФорма.ФоновоеИдентификатор);
если ФЗ=Неопределено тогда
ОтключитьОбработчикОжидания("ИндикаторВыполненияЗагрузки");
возврат ложь;
конецесли;
ФСообщения=ПолучитьСообщенияФЗ(ФЗ,,истина);
Если ФСообщения.Количество() > 0 Тогда
Для Каждого Сообщение Из ФСообщения Цикл
Сообщить(Сообщение);
если найти(Сообщение,"%")>0 тогда
прог=Число(СтрЗаменить(СтрЗаменить(Сообщение,"Выполнено ",""),"%",""));
конецесли;
если найти(Сообщение,"Результат:")>0 тогда
ИмяФайла=СтрЗаменить(Сообщение,"Результат:","");
Текст = Новый ЧтениеТекста(КаталогВременныхФайлов()+ИмяФайла, КодировкаТекста.UTF8);
СтрокаJson = JsonВСтруктуру(Текст.Прочитать());
ОтключитьОбработчикОжидания("ИндикаторВыполненияЗагрузки");
конецесли;
КонецЦикла;
КонецЕсли;
возврат прог;
КонецФункции
В результате будет что-то вроде:











