Книга знаний |
|
| 1С:Предприятие / Приемы программирования / Встроенный язык |
|
| В бытность свою студентом, курсе на 1, открыл для себя в Delphi замечательную возможность создания
<br>многопоточных приложений. По делу и без дела, делал <br><br>многопоточными все свои поделки – было интересно, хоть тогда у меня еще не было многоядерных <br>процессоров. Постепенно мозги привыкли к этому, и когда я <br><br>занялся 1С 8, меня ожидало разочарование – запущенный из формы код замораживал не только саму <br>форму, но и окно приложения заодно. Грустно. «Финты ушами» с <br><br>использованием генератора «Внешних событий» по душе не пришлись. А до фоновых заданий в версии <br>1С 8.1 добрался только сейчас. | Автор статьи: shachneff | Редакторы: oleg_km, dj_serega Последняя редакция №15 от 23.06.14 | История URL: http://kb.mista.ru/article.php?id=696 |
Процедура ФоноваяПроцедура(Вход) Экспорт
ВремяСтарта = ТекущаяДата();
Длит = 15; //15 секунд
Пока (ТекущаяДата() - ВремяСтарта) < Длит Цикл
//холостой цикл-замедлитель
КонецЦикла;
//чтобы не передавать примитивные типы,
//создадим ТЗ из двух колонок, в одну из которых положим значение входного параметра,
// а во вторую - выходного
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Вход");
ТЗ.Колонки.Добавить("Выход");
НС = ТЗ.Добавить();
НС.Вход = Вход;
НС.Выход = ТекущаяДата() + 3600;
//упакуем объект ТаблицаЗначений и сериализуем его в строку. Для больших таблиц - хороший выигрыш в объеме.
Упаковано = ЗначениеВСтрокуВнутр(Новый ХранилищеЗначения(ТЗ, Новый СжатиеДанных(9)));
ВызватьИсключение Упаковано; //самое главное, обманем систему, сказав, что возникла ошибка, и в качестве описания ошибки подсунем возвращаемое значение
КонецПроцедуры
Перем Ключ;
Процедура КнопкаВыполнитьНажатие(Кнопка)
//размерность массива - по числу параметров запускаемой в фоновом режиме процедуры
МассивПараметров = Новый Массив(1);
МассивПараметров[0] = "123-входной параметр-строка";
Ключ = Новый УникальныйИдентификатор; //чтобы отличить наше фоновое задание от других
//внимание! Первый параметр - полный путь к запускаемой процедуре, включая имя общего модуля, в котором она находится.
ФоновыеЗадания.Выполнить("МодульРегламентныхЗаданий.ФоноваяПроцедура", МассивПараметров, Ключ, "Тестовое ФЗ"); // запуск
ПодключитьОбработчикОжидания("ЗаполнитьТП", 1); //ждем, пока ФЗ нам что-то вернет.
//Важно! В данном случае применить метод ОжидатьЗавершения не получится. Если получится - пишите как.
КонецПроцедуры
Процедура ЗаполнитьТП() //просто заполняет ТабличноеПоле на форме, демонстрируя, что все работает.
ФильтрОтбора = Новый Структура("Ключ,Наименование,Состояние", Ключ, "Тестовое ФЗ", СостояниеФоновогоЗадания.ЗавершеноАварийно);
МассивЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(ФильтрОтбора);
Если МассивЗаданий.Количество() > 0 И НЕ МассивЗаданий[0].ИнформацияОбОшибке.Описание = "" Тогда
//получили данные из Фонового задания, поместили их в Табличное поле
ТП = ЗначениеИзСтрокиВнутр(МассивЗаданий[0].ИнформацияОбОшибке.Описание).Получить();
ЭлементыФормы.ТП.СоздатьКолонки(); //отобразили то, что поместили.
ОтключитьОбработчикОжидания("ЗаполнитьТП"); //прекратили ожидать результат от фонового задания.
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПриЗакрытии()
// При закрытии нужно отключить обработчик ожидания
ОтключитьОбработчикОжидания("ОжиданиеРезультатаВыполнения");
// Возможно, задание не было выполнено. Нужно его отменить
ОтменитьЗаданиеНаСервере();
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьВФоне(Команда)
// Работа с фоновыми заданиями возможна только на сервере
ВыполнитьВФонеНаСервере();
// Подключать обработчики ожидания можно на клиенте
ПодключитьОбработчикОжидания("ОжиданиеРезультатаВыполнения", 1);
КонецПроцедуры
&НаСервере
Процедура ВыполнитьВФонеНаСервере()
// "пихаем" дерево значений в объект
ДеревоОбъект = РеквизитФормыВЗначение("Дерево", Тип("ДеревоЗначений"));
// В этой переменной храним параметры для выполнения фонового задания
СтруктураПараметров = Новый Структура;
СтруктураПараметров.Вставить("Дерево", ДеревоОбъект);
СтруктураПараметров.Вставить("ОтборНачалоПериода", Объект.НачалоПериода);
СтруктураПараметров.Вставить("ОтборКонецПериода", Объект.КонецПериода);
// Помещаем данные параметров в хранилище значения и пакуем их в XML строку.
XMLСтруктура = XMLСтрока(Новый ХранилищеЗначения(СтруктураПараметров, Новый СжатиеДанных(9)));
// Заполняем массив параметров фонового задания
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(XMLСтруктура);
// Вызываем запуск фонового задания.
// Ключом являеся уникальный идентификатор формы.
ФоновыеЗадания.Выполнить("ОбщийМодуль1.ВыполнитьФоновыйКод", МассивПараметров, УникальныйИдентификатор, "Вывод данных через фоновое задание");
КонецПроцедуры // ВыполнитьВФонеНаСервере
&НаКлиенте
Процедура ОжиданиеРезультатаВыполнения() Экспорт
// Задание запустилось. Ожидаем завершения.
// Переменная по которой будем знать на клиенте, что фоновое задание завершилось
ЕстьРезультат = Ложь;
// Опять же, работа с фоновыми заданиями возможна на сервере
ОжиданиеРезультатаВыполненияНаСервере(ЕстьРезультат);
Если ЕстьРезультат Тогда
ОтключитьОбработчикОжидания("ОжиданиеРезультатаВыполнения"); // Если задание выполнилось, отключаем обработчик ожидания
КонецЕсли;
КонецПроцедуры // ОжиданиеРезультатаВыполнения
&НаСервере
Процедура ОжиданиеРезультатаВыполненияНаСервере(ЕстьРезультат)
// Выполним поиск фонового задания по Уникальному идентификатору формы, Наименованию и состоянию.
СтруктураОтбора = Новый Структура("Ключ, Наименование, Состояние", УникальныйИдентификатор, "Вывод данных через фоновое задание", СостояниеФоновогоЗадания.Завершено);
МассивЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(СтруктураОтбора);
Если МассивЗаданий.Количество() Тогда
// Нужное задание найдено. Можно получать данные и обрабатывать их.
ДеревоССервера = РеквизитФормыВЗначение("Дерево", Тип("ДеревоЗначений"));
XMLССервера = ХранилищеОбщихНастроек.Загрузить("ВыполнениеФоновогоЗадания", "ВыполнениеФоновогоЗадания");
ХранилищеССервера = XMLЗначение(Тип("ХранилищеЗначения"), XMLССервера);
ДеревоССервера = ХранилищеССервера.Получить();
ЗначениеВРеквизитФормы(ДеревоССервера, "Дерево");
ЕстьРезультат = Истина;
КонецЕсли;
// Можно добавить поиск заданий Активно, ЗавершеноАварийно или Отменено. Для теста не описывал проверки :)
КонецПроцедуры // ОжиданиеРезультатаВыполненияНаСервере
&НаСервере
Процедура ОтменитьЗаданиеНаСервере()
// Выполним поиск фонового задания по Уникальному идентификатору формы, Наименованию и состоянию.
СтруктураОтбора = Новый Структура("Ключ, Наименование, Состояние", УникальныйИдентификатор, "Вывод данных через фоновое задание", СостояниеФоновогоЗадания.Активно);
МассивЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(СтруктураОтбора);
Если МассивЗаданий.Количество() Тогда
// Задание найдено. Можно его отменить.
МассивЗаданий[0].Отменить();
КонецЕсли;
КонецПроцедуры // ПроверкаВыполненияНаСервере
Процедура ВыполнитьФоновыйКод() Экспорт
СтруктураПараметров = XMLЗначение(Тип("ХранилищеЗначения"), Параметр).Получить();
Дерево = СтруктураПараметров.Дерево;
// Выполняем произвольный код
...
...
// Подготавливаем данные в обработку
ТЗXML = XMLСтрока(Новый ХранилищеЗначения(Дерево));
ХранилищеОбщихНастроек.Сохранить("ВыполнениеФоновогоЗадания", "ВыполнениеФоновогоЗадания", ТЗXML);
КонецПроцедуры // ВыполнитьФоновыйКод
Описание
| Рубрикатор
| Поиск
| ТелепатБот
| Захваченные статьи
| Установки
| Форум
|