Книга знаний |
|
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); КонецПроцедуры // ВыполнитьФоновыйКод
Описание
| Рубрикатор
| Поиск
| ТелепатБот
| Захваченные статьи
| Установки
| Форум
|