Фоновые задания в файловом режиме 1С 8.x средствами 1С без дополнительных компонент

Опубликовал kosilov в раздел Обмен - 1С7.7 <-> 1C8.X

Необходимость использования фоновых задач в файловом варианте есть, а вот возможность как это осуществить совсем не очевидна.
Можно конечно воспользоваться дополнительными Active-X компонентами (http://infostart.ru/public/66660/) или запускать две копии приложения. Я же нашел (как мне) кажется более простой и гибкий вариант и при этом все только средствами самой 1С.

Понадобилось мне в фоне длительные операции делать и при этом чтобы пользователь мог спокойно работать с программой. В 8.1 появились фоновые задания, которые предназначены как раз для этой цели. Но оказывается всё не так просто. Всё хорошо в клиент\серверном варианте, а вот в файловом...

Для того, чтобы можно было выполнять фоновые задания должы быть:

1. До запуска фонового задания вызвана процедура "ВыполнитьОбработкуЗаданий()"

2. Для собственно выполнения заданий должна периодически вызываться процедура ВыполнитьОбработкуЗаданий()

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

При Com соединении вызывать эту процедуру тоже бестолку, так как опять таки синхронная работа (ожидание вызывающим вызываемого).

 Но оказывается из этого замкнутого круга есть выход.

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

Я сделал так:

1. Добавил специального пользователя Server (в списке не выводить)

2. Определил глобальную экспотрную переменную V8Com в модуле приложения .

3. В модуле приложения добавил следущий код:

 

Перем V8Com Экспорт;


Процедура
ПередНачаломРаботыСистемы(Отказ)

если
ИмяПользователя() = "Server" тогда
     
ПодключитьОбработчикОжидания("ОбработчикОжидания",1);
КонецЕсли;

КонецПроцедуры

Процедура
ОбработчикОжидания() экспорт
     
ВыполнитьОбработкуЗаданий();
КонецПроцедуры

Если обрабатывать фоновые задания необходимо сразу, а не по специальному требованию пользователя, то можно прямо в модуле приложения добавить:

 

V8Com = Новый COMОбъект("V81.Application");

Попытка
   
Открытие = V8Com.Connect(СтрокаСоединенияИнформационнойБазы()+ "Usr=""Server"";Pwd=""123"";");
Исключение
   
Предупреждение("Ошибка открытия фоновой копии!!!");
   
Отказ = истина;
    Возврат;
КонецПопытки;

В противном случае этот код исполняем по требованию пользователя из формы или откуда угодно.

После можно запускать фоновые задания штатными методами. 

Например: ФоновыеЗадания.Выполнить("ОбработкаФоновыхЗаданий.ВыполнитьЦикл",
МассивПараметров,"Индикатор2");

В демонстрационной обработке можно посмотреть как это работает.

За основу обработки я взял обработку от сюда.

Кое-что правда не удалось (по крайней мере пока):

 1. Не получилось использовать обработчики событий для обмена данными между фоновой копией и основной. Не ясно какое и как событие генерировать в фоновой функции и как его потом ловить в главном приложении. (если кто знает подскажите). В демонстрационной конфигурации передача данных происходит через регистр сведений. 

2. Задания выполняются не параллельно, а по очереди. Судя по всему причина такого поведения в особенностях работы процедуры ВыполнитьОбработкуЗаданий() внутри Обработчика ожидания. То ли обработчик ожидания не прерывается (активности пользователя ведь для фоновой копии быть не может), то ли просто выполнение заданий задумано так.  

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

P.S. Если такое решение "всем известно", то прошу меня сильно не бить, так как я еще неделю назад активно искал решение но не нашел. Вариант с внешней Active-X компонентой у меня не заработал.      

Наименование
Фоновые задания в файловой среде
Скачать

См. также

Выгрузка данных из Управления торговлей 10.3 в Бухгалтерию предприятия, ред. 3.0 (Версия 1.6.7)
Коллекция полезных кнопок и процедур для отчетов и обработок v3.00
Выгрузка/загрузка для отличающихся конфигураций (документы, справочники, ПВХ, ПВР, счета)
Автоматизированная компоновка проектной документации (в Word, с рисунками и моделями)
Шаблон обработки для ТСД, операция "Перемещение", каркасная конфигурация
DT:Менеджер 8.2 (Распаковка *.DT. Быстрый экспорт конфигурации. Сброс пользователей. Работа с "битыми" DT)
Автоматическое закрытие заказов покупателей (или напоминания о незакрытых), для УТ 10.3
TurboConf - турбина для Конфигуратора
Полезности применения СКД
[1С 8] Мегапрайс: Помощник закупок (анализ продаж, анализ остатков, анализ прайсов) Планирование и автоматизация закупок...
[1С 8] Мегапрайс: Загрузка из EXCEL в 1С (импорт прайсов, номенклатуры, цен, документов) Версия COZILY 2015
Мастер загрузки из Excel в 1С - номенклатура, цены, документы (3.0)

Комментарии

1. Evg-Lylyk 19.05.2010 12:36
На эту же тему http://infostart.ru/public/16486/
Ответили: (2)
# Ответить
2. kosilov 19.05.2010 22:05
(1) Да, это тоже вариант. Но в моем варианте используется стандартный механизм фоновых заданий. Ком соединие используется только для того, чтобы выполнять задания, т.е. запускать стандартную функцию "выполнить задания".
# Ответить
3. kosilov 19.05.2010 22:20
Вот тут пишут человек, что штатными способами вернуть результат работы невозможно из фонового задания. Для клиент\серверного варианта наверное действительно только через базу (хотя можно изучить возможность через временую таблицу).
Для файлового варианта, интуитивно чувствую что как-то можно через нотификации. Я просто немного запутался в них. Есть внешник, а есть внутренние, есть еще каие-то функции установки обработчиков. Что с чем стыкуется и какова "видимость" мне пока не ясно. Если есть кто на этом собаку съел поделитесь опытом.
Суть вопроса в следующем:
1. Как сгенерировать сообщение (событие, нотификацию) в 1С, которое передасться через ком соединение вызывающем приложению. Т.е. Чтобы его можно было поймать как в данном стандартном примере:
msword = New COMObject("Word.Application");
AddHandler msword.DocumentChange, WhenDocumentChange
Procedure WhenDocumentChange()
	Message("Document is changed");
EndProcedure 
...Показать Скрыть


2. Как другим сопсобом сгенерить сообщение (например Notify - уведомить), чтобы как-то его отловить в другом сообщении.
Ответили: (4)
# Ответить
4. kosilov 19.05.2010 22:36
(3) И вот еще как можно передать данные при данном варианте от отработавшего задания:
1. В глобальном модуле определяем переменную:
Перем РезультатыФоновойРаботы Экспорт;

А потом в конце:
РезультатыФоновойРаботы = новый Соответствие;

Плюс функция:
Функция ВернутьРезультатФоновогоЗадания(Ключ) Экспорт
 Рез = РезультатыФоновойРаботы[Ключ];
 РезультатыФоновойРаботы.Удалить(Ключ);
возврат Рез;
конецфункции
...Показать Скрыть


При выполнении фонового задания, фоновая функция должна знать свой ключ, т.е. его надо передавать ей параметром.
После выполнения функции перед конецфункции пишем:
РезультатыФоновойРаботы[Ключ] = <Наш результат работы в виде чего угодно>

И вуаля:
Запускаем фоновое задание. Отслеживаем его завершение через стандартный механизм: ФоновыеЗаданияПолучитьФоновыеЗадания или ФоновыеЗадания.НайтиПоУникальномуИдентификатору.
А затем обращаемся к наему глобальному ком объекту.
Рез = V8Com.ВернутьРезультатФоновогоЗадания(Ключ);
В данном случае это будет синхронный вызов и мы получим результат.

Мне кажется, что это элегантно.
# Ответить
5. dushelov 25.05.2010 18:03
Кстати, обычные фоновые задания довольно часто зависают. Решения проблемы так и не нашли - только перезапуск сервиса.
Ответили: (6)
# Ответить
6. kosilov 26.05.2010 00:56
(5) Пока не сталкивался. А как виснут? В смысле виснет среда?
А что 1С по этому поводу говорит?
Ответили: (7)
# Ответить
7. dushelov 26.05.2010 01:05
(6) В смысле то, что фоновое задание висит бесконечно со статусом "выполняется" и никак его не удалить, ни через консоль заданий, ни через консоль серверов, что в 8.1, что в 8.2 встречается. Поэтому и пришлось писать свою компоненту для многопоточности.
# Ответить
8. sas2006 29.10.2010 15:12
У у меня появился вопрос, получается будет запускаться еще одна копия 1с и следовательно должна быть еще одна свободная лицензия?
# Ответить
9. Kazan 12.10.2011 06:14
не понятно какой конкретно оператор запускает механизм выполнения заданий от имени сервера - ВыполнитьОбработкуЗаданий или оновыеЗадания.Выполнить ???
# Ответить
10. krevedgo (файл скачал) 27.12.2012 23:03
Спасибо автору за тему!
Очень нужная вещь, но...
Помогите плиз начинающему
Что куда вписывать? Платформа 8.2
Открыл конфигуратор, открыл модуль управляемого приложения
Сделал так:
// Конец СтандартныеПодсистемы
Перем V8Com Экспорт;

Процедура ПередНачаломРаботыСистемы(Отказ)
	
	// СтандартныеПодсистемы
	СтандартныеПодсистемыКлиент.ДействияПередНачаломРаботыСистемы(Отказ);
	// Конец СтандартныеПодсистемы
	
	//выполняем фоновые задания
если ИмяПользователя() = "Server" тогда
       ПодключитьОбработчикОжидания("ОбработчикОжидания",1);
   КонецЕсли;
   //конец выполняем фоновые задания

	
КонецПроцедуры

 Процедура ОбработчикОжидания() экспорт
       ВыполнитьОбработкуЗаданий();
 КонецПроцедуры

Процедура ПриНачалеРаботыСистемы()
	
	НеобходимаНачальнаяНастройкаПрограммы = ОбновлениеИнформационнойБазыУТ.НеобходимаНачальнаяНастройкаПрограммы();
	
	// СтандартныеПодсистемы
	СтандартныеПодсистемыКлиент.ДействияПриНачалеРаботыСистемы(Истина);
	// Конец СтандартныеПодсистемы
	
	//Диалог выбора варианта настройки системы
	Если НеобходимаНачальнаяНастройкаПрограммы Тогда
		ОткрытьФормуМодально("ОбщаяФорма.ВыборВариантаНастройкиПрограммы");
	КонецЕсли;
	//Конец Диалог выбора варианта настройки системы
	
	//ОткрытиеФормПриНачалеРаботыСистемы
	ОткрытиеФормПриНачалеРаботыСистемыКлиент.ПриНачалеРаботыСистемы();
	//Конец ОткрытиеФормПриНачалеРаботыСистемы
	
	V8Com = Новый COMОбъект("V81.Application");

 Попытка
     Открытие = V8Com.Connect(СтрокаСоединенияИнформационнойБазы()+ "Usr=""Server"";Pwd=""123"";");
 Исключение
     Предупреждение("Ошибка открытия фоновой копии!!!");
     Отказ = истина;
     Возврат;
 КонецПопытки;

КонецПроцедуры

...Показать Скрыть


Запускаю отладку и получаю ошибку
{МодульУправляемогоПриложения(97)}: Ошибка при вызове конструктора (COMОбъект)
V8Com = Новый COMОбъект("V81.Application");
по причине:
Недопустимая строка с указанием класса


Попробовал это - не помогло.

Подскажите, что я делаю не так?
Смущает "СтрокаСоединенияИнформационнойБазы" - может тут должно быть что-то более конкретное?
Требуется выполнять всего одно задание "обмен с сайтом", как-то в УТ10 это работало без дополнительной химии, а вот в УТ11 уже не получается.
Ответили: (11)
# Ответить
11. nikbrik 07.02.2013 16:50
(10)
Что куда вписывать? Платформа 8.2
V8Com = Новый COMОбъект("V81.Application");

Ответ очевиден:
V8Com = Новый COMОбъект("V82.Application");

Вопрос: метод работает, фоновые задания выполняются, НО необходимо фоновым заданием принудительно завершить работу пользователя в определенное время. Если запускал от имени текущего пользователя - все работало, но с этим методом вообще ничего не происходит. Может нашли уже какой-то способ передать сообщение о выполнении задания?
# Ответить
12. kosilov 07.02.2013 17:43
Уже не припомню.

Но как крайний вариант, сделайте так:
1. Создайте регистр сведений или используйте какой-то предопределенный элемент БД, который синхронизируется между разными потоками.
2. На клиентком процессе сделайе регулярный опрос ( каждый 30 сек например) этого регистра (или эл-та который вы использовали).
3. Если фоновый поток требует завершения пользователей,то в БД выставляется флаг (в этот ваш эл-т или регистр)
4. Клиентский поток смотрит это значение и если там стоит флаг завершения, то клиентский поток сам завершается по собственному т.с. желанию.

Если, я конечно правильно понял вашу задачу.
Ответили: (13)
# Ответить
13. nikbrik 07.02.2013 17:58
(12)Спасибо за ответ
Дело в том, что фоновый процесс нужен был, чтобы в файловом варианте не мешать работе пользователя постоянными проверками фоновых заданий. А то что вы предлагаете - значит опять проверять каждые 30 секунд на наличие флага) опять будут подвисания, тогда просто нет смысла в фоновом процессе... Или может я ошибаюсь, и есть способ проверять на наличие флага как-то незаметно?
P.S. Извините что не могу более ясно выражать мысли)) после работы голова гудит...
# Ответить
14. kosilov 07.02.2013 19:15
Я пробовал играться с нотификациями, но что-то не очень у меня это получилось.

У вас таймаут большой может быть (будет не критично) 30 сек или минута.
Там есть хэндлер (к сожалению уже не помню название) который может быть вызван только тогда когда нет активности на стороне пользователя. Если вы используете этот метод, то пользователь не будет замечать что система что-то опрашивает.
# Ответить
Внимание! Для написания сообщения необходимо авторизоваться
Текст сообщения*
Прикрепить файл