1. Код модуля формы внешней обработки
//Устанавливаем количество обновлений индикатора на сервере.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Обновлений = 10;
КонецПроцедуры
//Обнуляем прогресс бар, запускаем фоновую процедуру на сервере, подключаем обработчик ожидания
&НаКлиенте
Процедура НачатьИндикацию(Команда)
Прогресс = 0;
ВыполнитьНаСервере(УникальныйИдентификатор, Обновлений);
ПодключитьОбработчикОжидания(«ОбработчикОжидания», 1, Ложь);
КонецПроцедуры
//Получаем сообщения от фонового задания и прогресс операции. Если операция закончилась отключаем обработчик ожидания.
&НаКлиенте
Процедура ОбработчикОжидания()
ПолучитьПрогрессВыполнения(УникальныйИдентификатор, Прогресс);
Состояние(НСтр(«ru = ‘Тест прогресс бара'»), Прогресс, НСтр(«ru = ‘Пустой цикл для тестирования'»));
Если Прогресс = 100 Тогда
ОтключитьОбработчикОжидания(«ОбработчикОжидания»);
КонецЕсли;
КонецПроцедуры
//Устанавливаем привилегированный режим, если у пользователя нет административных прав. Запускаем фоновое задания из внешней обработки с помощью метода который доступен в УТ 11.
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере(УникальныйИдентификатор, Обновлений)
УстановитьПривилегированныйРежим(Истина);
ЗаданиеПараметры = Новый Массив();
ЗаданиеПараметры.Добавить(Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию(«Прогрес-бар [0.0.1]»));
ЗаданиеПараметры.Добавить(Новый Структура(«Обновлений», Обновлений));
ЗаданиеПараметры.Добавить(Неопределено);
ЗаданиеПараметры.Добавить(Неопределено);
ФоновоеЗадание = ФоновыеЗадания.Выполнить(«ДополнительныеОтчетыИОбработки.ВыполнитьОбработкуНепосредственно», ЗаданиеПараметры, УникальныйИдентификатор, «ИндикацияПроцеса»);
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПолучитьПрогрессВыполнения(УникальныйИдентификатор, Прогресс)
НайденныеЗадания = ФоновыеЗадания.ПолучитьФоновыеЗадания(Новый Структура(«Ключ», УникальныйИдентификатор));
Если НайденныеЗадания.Количество() = 0 Тогда Возврат; КонецЕсли;
Задание = НайденныеЗадания[0];
Если Задание.Состояние = СостояниеФоновогоЗадания.Активно Тогда
МассивСообщений = Задание.ПолучитьСообщенияПользователю(Истина);
Если МассивСообщений = Неопределено Тогда Возврат; КонецЕсли;
Для Каждого Сообщение Из МассивСообщений Цикл
Если Строка(Сообщение.ИдентификаторНазначения) = «00000000-0000-0000-0000-000000000000» Тогда
Прогресс = Число(Сообщение.Текст);
Иначе
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Сообщение.Текст, Сообщение.КлючДанных, Сообщение.Поле, Сообщение.ПутьКДанным);
КонецЕсли;
КонецЦикла;;
Иначе
Прогресс = 100;
КонецЕсли;
КонецПроцедуры
2. Код модуля объекта внешней обработки
Функция СведенияОВнешнейОбработке() Экспорт
Версия = «0.0.1»;
// Объявим переменную, в которой мы сохраним и вернем «наружу» необходимые данные
ПараметрыРегистрации = Новый Структура;
// Объявим еще одну переменную, которая нам потребуется ниже
МассивНазначений = Новый Массив;
// Первый параметр, который мы должны указать — это какой вид обработки системе должна зарегистрировать.
// Допустимые типы: ДополнительнаяОбработка, ДополнительныйОтчет, ЗаполнениеОбъекта, Отчет, ПечатнаяФорма, СозданиеСвязанныхОбъектов
ПараметрыРегистрации.Вставить(«Вид», «ДополнительнаяОбработка»);
// Теперь нам необходимо передать в виде массива имен, к чему будет подключена наша ВПФ
// Имейте ввиду, что можно задать имя в таком виде: Документ.* — в этом случае обработка будет подключена ко всем документам в системе,
// которые поддерживают механизм ВПФ
//СчитатьДокументыНазначений(МассивНазначений);
ПараметрыРегистрации.Вставить(«Назначение», Новый Массив);
// Теперь зададим имя, под которым ВПФ будет зарегистрирована в справочнике внешних обработок
ПараметрыРегистрации.Вставить(«Наименование», «Прогрес-бар [» + Версия + «]»);
// Зададим право обработке на использование безопасного режима. Более подробно можно узнать в справке к платформе (метод УстановитьБезопасныйРежим)
ПараметрыРегистрации.Вставить(«БезопасныйРежим», Ложь);
// Следующие два параметра играют больше информационную роль, т.е. это то, что будет видеть пользователь в информации к обработке
ПараметрыРегистрации.Вставить(«Версия», Версия);
ПараметрыРегистрации.Вставить(«Информация», «Прогрес-бар [» + Версия + «]»);
// Создадим таблицу команд (подробнее смотрим ниже)
ТаблицаКоманд = ПолучитьТаблицуКоманд();
// Добавим команду в таблицу
ДобавитьКоманду(ТаблицаКоманд, «Прогрес-бар [» + Версия + «]», «BP», «ОткрытиеФормы», Ложь, «BP»);
// Сохраним таблицу команд в параметры регистрации обработки
ПараметрыРегистрации.Вставить(«Команды», ТаблицаКоманд);
// Теперь вернем системе наши параметры
Возврат ПараметрыРегистрации;
КонецФункции
Функция ПолучитьТаблицуКоманд()
// Создадим пустую таблицу команд и колонки в ней
Команды = Новый ТаблицаЗначений;
// Как будет выглядеть описание печатной формы для пользователя
Команды.Колонки.Добавить(«Представление», Новый ОписаниеТипов(«Строка»));
// Имя нашего макета, что бы могли отличить вызванную команду в обработке печати
Команды.Колонки.Добавить(«Идентификатор», Новый ОписаниеТипов(«Строка»));
// Тут задается, как должна вызваться команда обработки
// Возможные варианты:
// — ОткрытиеФормы — в этом случае в колонке идентификатор должно быть указано имя формы, которое должна будет открыть система
// — ВызовКлиентскогоМетода — вызвать клиентскую экспортную процедуру из модуля формы обработки
// — ВызовСерверногоМетода — вызвать серверную экспортную процедуру из модуля объекта обработки
Команды.Колонки.Добавить(«Использование», Новый ОписаниеТипов(«Строка»));
// Следующий параметр указывает, необходимо ли показывать оповещение при начале и завершению работы обработки. Не имеет смысла при открытии формы
Команды.Колонки.Добавить(«ПоказыватьОповещение», Новый ОписаниеТипов(«Булево»));
// Для печатной формы должен содержать строку ПечатьMXL
Команды.Колонки.Добавить(«Модификатор», Новый ОписаниеТипов(«Строка»));
Возврат Команды;
КонецФункции
Процедура ДобавитьКоманду(ТаблицаКоманд, Представление, Идентификатор, Использование, ПоказыватьОповещение = Ложь, Модификатор = «»)
// Добавляем команду в таблицу команд по переданному описанию.
// Параметры и их значения можно посмотреть в функции ПолучитьТаблицуКоманд
НоваяКоманда = ТаблицаКоманд.Добавить();
НоваяКоманда.Представление = Представление;
НоваяКоманда.Идентификатор = Идентификатор;
НоваяКоманда.Использование = Использование;
НоваяКоманда.ПоказыватьОповещение = ПоказыватьОповещение;
НоваяКоманда.Модификатор = Модификатор;
КонецПроцедуры
// Пощитаем коэффициенты и сделаем соответствие чтобы знать когда обновлять прогресс.
Процедура ВыполнитьКоманду(Параметры) Экспорт
Обновлений = Параметры.Обновлений;
Итераций = 10000000;
Коэф = Цел(Итераций / Обновлений);
КоэфОбн = 100 / Обновлений;
ТочкиОбновления = Новый Соответствие;
Для i = 1 По Обновлений Цикл ТочкиОбновления[i * Коэф] = Цел(i * КоэфОбн); КонецЦикла;
Сообщение = Новый СообщениеПользователю;
Сообщение.ИдентификаторНазначения = Новый УникальныйИдентификатор;
Сообщение.Текст = «Фоновая обработка данных успешно началась.»;
Сообщение.Сообщить();
Для i = 1 По Итераций Цикл
Если ТочкиОбновления[i] <> Неопределено Тогда ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Строка(ТочкиОбновления[i])); КонецЕсли;
// Основной код.
КонецЦикла;
КонецПроцедуры
Плюсы:
- Не нужно изменять основную конфигурацию;
- все очень просто в реализации и использовании;
- пользователь видит прогресс и одновременно делает что-то еще.
не понял, почему для SQL.
(1) Stamper, в файловой версии менеджер заданий не активен. И задания выполняются по очереди, а не асинхронно. Комментарий актуален к УТ 11, может в других конфигурациях есть выход.
(2)
пожалуйста, немного поподробнее расскажи! или может быть, есть ссылочка?
(3) Stamper, В файловом варианте задания всегда выполняются последовательно одно за другим, в отличие от клиент-серверного варианта, где несколько заданий могут выполняться параллельно в одном и том же рабочем процессе или в разных рабочих процессах и даже на разных компьютерах. Поэтому, выделенного клиента, занимающегося обработкой заданий, не рекомендуется использовать для других целей, т.к. это может негативно повлиять на производительность выполнения заданий.
Клиенты в файловом варианте не имеют прямой связи с планировщиком заданий и взаимодействуют с ним через файл обмена, который находится в каталоге информационной базы (в клиент-серверном варианте клиенты соединены с планировщиком по TCP/IP, что позволяет избежать задержек при назначении заданий на выполнение). Поэтому при обработке заданий возможны небольшие задержки, связанные с тем, что планировщик читает файл обмена и получает очередную порцию заданий на выполнение только после того, как завершит выполнение полученных ранее заданий.
http://www.bit.ly/TO6csq
(4) можно было не объяснять почему это не работает в файловом варианте, а просто ответить: нет необходимости таких заморочек с ПрогрессБаром, т.к. можно управлять формой Прогресса — Явно;)
Есть какая-дь более эффективная процедура управления Прогресс-баром из текущей формы внешней обработки при запуске длительной Глобальной процедуры на сервере, не меняя конфигурацию, притом что серверная процедура меняет значения элементов этой формы, но обновления реквизитов формы (ПрогрессБар + СтатуснаяСтрока) мы можем увидеть только по окончании выполнения на сервере и возврате в клиентский контекст?
Спасибо, добавил плановому отделу в их обработочку) Теперь приятно радует глаз)
А то все время были возмущения, мол нихрена не понятно, работает или зависло, а текстовое представления работы обработки им не нравилось…
(5)В УФ такой процедуры нет. Можно реализовать это прыжками между контекстами «&НаКлиенте» на «&НаСервере», то есть порцию обработали в контексте сервера, вернулись на контекст клиента — показали прогресс, далее возвращаемся на контекст сервера для обработки следующей порции. Этот метод очень негативно влияет на время выполнения длительной операции.
— Да, обновление интерфейса состоится только после возвращения в контекст клиента.
В обычных формах проблем нет, для их реализовано множество различных ПрогрессБаров.
Бухгалтерия предприятия, редакция 3.0 (3.0.39.60)
При выполнении выдает ошибку:
{Форма.Форма.Форма(43)}: Ошибка при вызове метода контекста (Выполнить)
ФоновоеЗадание = ФоновыеЗадания.Выполнить(«ДополнительныеОтчетыИОбработки.ВыполнитьОбработкуНепосредственно», ЗаданиеПараметры, УникальныйИдентификатор, «ИндикацияПроцеса»);
по причине:
Метод задания не найден: ДополнительныеОтчетыИОбработки:ВыполнитьОбработкуНепосредственно
Управление торговлей, редакция 11.1 (11.1.6.20)
При выполнении выдает ошибку:
Метод задания не найден: ДополнительныеОтчетыИОбработки:ВыполнитьОбработкуНепосредственно
(8) velber, возможно, в БСП изменилось название метода или убрали ключевое слово «Экспорт» или изменились свойства общего модуля
В типовых есть функция ДополнительныеОтчетыИОбработки.ВыполнитьКоманду. Её можно использовать для обработчика фонового задания, чтобы выполнить свою обработку, помещенную в справочник внешних обработок.
При выполнении выдает ошибку:
Метод задания не найден: ДополнительныеОтчетыИОбработки:ВыполнитьОбработкуНепосредственно
Можно тыкнуть пальцем, где взять этот код. В УТ11 я его не обнаружил. Ни в старой, ни в новой.
(12) yuha33, посмотрите здесь как сделаноhttp://infostart.ru/public/405368/ . Работает под УТ 11
Подскажите, будут ли доступны в фоновом исполнении остальные процедуры/функции модуля объекта обработки из процедуры «ВыполнитьКоманду(Параметры)» ?
(14) Andreyyy, будут доступны в контексте фонового задания только те методы, которые есть в самой обработке фонового задания. Так же контекст обработки, что инициировала фоновое задание будет недоступен.