Понадобилось мне в фоне длительные операции делать и при этом, чтобы пользователь мог спокойно работать с программой. В 8.1 появились фоновые задания, которые предназначены как раз для этой цели. Но оказывается всё не так просто. Всё хорошо в клиент\серверном варианте, а вот в файловом...
Для того чтобы можно было выполнять фоновые задания необходимо, чтобы:
- До запуска фонового задания была вызвана процедура "ВыполнитьОбработкуЗаданий()"
- Для собственно выполнения заданий должна периодически вызываться процедура ВыполнитьОбработкуЗаданий()
Выполняется эта процедура не асинхронно и следовательно, если прикрутить её в обработчик ожидания, то пользователю работать будет очень не комфортно (дергает).
При Com-соединении вызывать эту процедуру тоже без толку, так как опять таки синхронная работа (ожидание вызывающим вызываемого).
Но оказывается из этого замкнутого круга есть выход.
При установлении Com-соединения исполняется глобальный модуль (новой копии) после чего управление возвращается вызывающему процессу. При этом если в главном модуле инициирован обработчик ожидания, то функция обработки будет вызываться асинхронно (асинхронно с точки зрения приложения открывшего соединение с Com-объектом, но не для самого Com-объекта). Этим и воспользуемся.
Я сделал так:
- Добавил специального пользователя Server (в списке не выводить)
- Определил глобальную экспортную переменную V8Com в модуле приложения .
- В модуле приложения добавил следующий код:
Перем V8Com Экспорт;
Процедура ПередНачаломРаботыСистемы(Отказ)
Если ИмяПользователя() = "Server" тогда
ПодключитьОбработчикОжидания("ОбработчикОжидания",1);
КонецЕсли;
КонецПроцедуры
Процедура ОбработчикОжидания() экспорт
ВыполнитьОбработкуЗаданий();
КонецПроцедуры
Если обрабатывать фоновые задания необходимо сразу, а не по специальному требованию пользователя, то можно прямо в модуле приложения добавить:
V8Com = Новый COMОбъект("V81.Application");
Попытка
Открытие = V8Com.Connect(СтрокаСоединенияИнформационнойБазы()+ "Usr=""Server"";Pwd=""123"";");
Исключение
Предупреждение("Ошибка открытия фоновой копии!!!");
Отказ = истина;
Возврат;
КонецПопытки;
В противном случае этот код исполняем по требованию пользователя из формы или откуда угодно.
После можно запускать фоновые задания штатными методами.
Например:
ФоновыеЗадания.Выполнить("ОбработкаФоновыхЗаданий.ВыполнитьЦикл", МассивПараметров,"Индикатор2");
В демонстрационной обработке можно посмотреть как это работает.
За основу обработки я взял обработку отсюда.
Кое-что правда не удалось (по крайней мере пока):
- Не получилось использовать обработчики событий для обмена данными между фоновой копией и основной. Не ясно какое и как событие генерировать в фоновой функции и как его потом ловить в главном приложении. (если кто знает, подскажите). В демонстрационной конфигурации передача данных происходит через регистр сведений.
- Задания выполняются не параллельно, а по очереди. Судя по всему причина такого поведения в особенностях работы процедуры ВыполнитьОбработкуЗаданий() внутри Обработчика ожидания. То ли обработчик ожидания не прерывается (активности пользователя ведь для фоновой копии быть не может), то ли просто выполнение заданий задумано так.
Но по сути это не проблема если выполнять надо одно задание, либо можно запускать несколько фоновых копий (по одной на каждое параллельное фоновое) либо организовывать так фоновую функцию, чтобы она периодически отдавала управление в процесе выполнения (т.е. запоминала н чем остановилась, а при следующем вызове продолжала с этого места по подробнее :)
P.S. Если такое решение "всем известно", то прошу меня сильно не бить, так как я еще неделю назад активно искал решение но не нашел. Вариант с внешней Active-X компонентой у меня не заработал.