Форум 1С
Программистам, бухгалтерам, администраторам, пользователям
Задай вопрос - получи решение проблемы
16 апр 2024, 10:02

Прервать Цикл

Автор Rasty, 25 мар 2015, 17:20

0 Пользователей и 1 гость просматривают эту тему.

Rasty

УТ 11.1 есть некий цикл, который может выполняться очень долго. Можно ли прервать выполнения цикла по нажатию кнопке на форме, если да, то где можно почитать?
ЗЫ ОбработкаПрерыванияПользователя(), хороший вариант, но интересно, что еще можно сделать=)
Помогли - Скажи спасибо! Решил сам - поделись решением!
:)

LexaK

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

как выход, разбивайте вашу обработку больших массив, таблиц на части, и частями в цикле на клиенте отправляйте на обработку на сервер, соответственно в цикле на клиенте поместите
ОбработкаПрерыванияПользователя().

либо еще каким-то образом, писать какое ни будь значение в переменную доступную на сервере,
и в большом цикле анализировать эту переменную, с таких вариантом не экспериментировал.

Может еще кто поделится опытом как прервать выполнение цикла на сервере.
если помогло нажмите: Спасибо!

Rasty

что делает цикл

Для Каждого стр из Объект.ТЧ Цикл
Сообщить(Стр.Штрихкод);
Процент =Стр.НомерСтроки*100/Объект.ТЧ.Количество();
Состояние("Запсиано",Процент);
ОбработкаПрерыванияПользователя();
RoyalRay.Write = Стр.Штрихкод;
КонецЦикла

Добавлено: 25 мар 2015, 17:42


Я смотрел как работает Удаление помеченных объектов, там собственно все выполняется в фоновом режиме. Может кто ткнуть несуразного рожей в то место, где можно подробней почитать?
Добавлено: 25 мар 2015, 17:59


Нашел такую штуку

Асинхронные вычисления без «заморозки» формы (на фоновых заданиях)

В бытность свою студентом, курсе на 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

Ключевые слова: 1cv81, фоновое задание, асинхронно, многопоточность

Дано:

1С:Предприятие > 8.1.8, клиент-серверная архитектура, MS SQL.
Общий неглобальный серверный модуль. Обработка с одной формой, одной кнопкой и одним табличным полем.

Цель:

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

Методика:

Как показала практика, из отработавшего фонового задания вернуть штатным путем каке-либо данные невозможно. Имеется 2 способа, позволяющих это
делать:
1) фоновое задание пишет результат своей работы в БД, обработка отслеживает, что фоновое задание завершилось и считывает из БД результат. В качестве места хранения результата предлагается
использовать регистр сведений, где измерение хранит UID экземпляра фонового задания, а ресурс имеет тип ХранилищеЗначений.
2) извращенный способ - передать значение через программную генерацию исключения (оператор «ВызватьИсключение»).

Решение:


Описывать способ с регистром сведений не буду, так как это достаточно просто реализовать, а минусом является необходимость добавления в конфигурацию регистра сведений. Поэтому опишу вариант с
«ВызватьИсключение»:

Процедура общего модуля:

Процедура ФоноваяПроцедура(Вход) Экспорт

ВремяСтарта = ТекущаяДата();
Длит = 15; //15 секунд
Пока (ТекущаяДата() - ВремяСтарта) < Длит Цикл
//холостой цикл-замедлитель
КонецЦикла;

//чтобы не передавать примитивные типы,
//создадим ТЗ из двух колонок, в одну из которых положим значение входного параметра,
// а во вторую - выходного
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Вход");
ТЗ.Колонки.Добавить("Выход");

НС = ТЗ.Добавить();
НС.Вход = Вход;
НС.Выход = ТекущаяДата() + 3600;

//упакуем объект ТаблицаЗначений и сериализуем его в строку. Для больших таблиц - хороший выигрыш в объеме.
Упаковано = ЗначениеВСтрокуВнутр(Новый ХранилищеЗначения(ТЗ, Новый СжатиеДанных(9)));


ВызватьИсключение Упаковано; //самое главное, обманем систему, сказав, что возникла ошибка, и в качестве описания ошибки подсунем возвращаемое значение

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

Модуль формы обработки:


Перем Ключ;

Процедура КнопкаВыполнитьНажатие(Кнопка)

//размерность массива - по числу параметров запускаемой в фоновом режиме процедуры
МассивПараметров = Новый Массив(1);
МассивПараметров[0] = "123-входной параметр-строка";
Ключ = Новый УникальныйИдентификатор; //чтобы отличить наше фоновое задание от других

//внимание! Первый параметр - полный путь к запускаемой процедуре, включая имя общего модуля, в котором она находится.
ФоновыеЗадания.Выполнить("МодульРегламентныхЗаданий.ФоноваяПроцедура", МассивПараметров, Ключ, "Тестовое ФЗ"); // запуск

ПодключитьОбработчикОжидания("ЗаполнитьТП", 1); //ждем, пока ФЗ нам что-то вернет.
//Важно! В данном случае применить метод ОжидатьЗавершения не получится. Если получится - пишите как.

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

Процедура ЗаполнитьТП() //просто заполняет ТабличноеПоле на форме, демонстрируя, что все работает.

ФильтрОтбора = Новый Структура("Ключ,Наименование,Состояние", Ключ, "Тестовое ФЗ", СостояниеФоновогоЗадания.ЗавершеноАварийно);
МассивЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(ФильтрОтбора);

Если МассивЗаданий.Количество() > 0 И НЕ МассивЗаданий[0].ИнформацияОбОшибке.Описание = "" Тогда
//получили данные из Фонового задания, поместили их в Табличное поле
ТП = ЗначениеИзСтрокиВнутр(МассивЗаданий[0].ИнформацияОбОшибке.Описание).Получить();
ЭлементыФормы.ТП.СоздатьКолонки(); //отобразили то, что поместили.
ОтключитьОбработчикОжидания("ЗаполнитьТП"); //прекратили ожидать результат от фонового задания.
КонецЕсли;

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

Результат:

Жмем кнопку. 15 секунд наслаждаемся перетаскиванием формы и прочими действиями (кроме закрытия).
Потом резко (само! шайтан! :) заполнится табличное поле на форме, чего и следовало ожидать.
Нагрузочные испытания проведены на передаче таблицы значений из 2 полей с количеством строк 100 тыс.
шт. - успешно.

Надеюсь, статья будет вам полезна.
Выражаю благодарность всем, кто помог мне осуществить данную операцию.

С уважением, Алексей Шачнев.

Конец.

Вместо обработки ожидания использовал отправку датаграммы из фонового задания форме посредством MS WinSock (ActiveX)

oleg_km

Нужно было выполнить заполнение дерева в фоне (что бы не блокировать основной интерфейс). Нашел эту статейку.
Собственно удалось выполнить фоновое задание без "ВызватьИсключение".
8.2.19.68 (Управляемое приложение)

Код во внешней обработке следующий:

&НаКлиенте
Процедура ПриЗакрытии()

// При закрытии нужно отключить обработчик ожидания
ОтключитьОбработчикОжидания("ОжиданиеРезультатаВыполнения");

// Возможно, задание не было выполнено. Нужно его отменить
ОтменитьЗаданиеНаСервере();

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


&НаКлиенте
Процедура ВыполнитьВФоне(Команда)

// Работа с фоновыми заданиями возможна только на сервере
ВыполнитьВФонеНаСервере();

// Подключать обработчики ожидания можно на клиенте
ПодключитьОбработчикОжидания("ОжиданиеРезультатаВыполнения", 1);

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

&НаСервере
Процедура ВыполнитьВФонеНаСервере()

// "пихаем" дерево значений в объект
ДеревоОбъект = РеквизитФормыВЗначение("Дерево", Тип("ДеревоЗначений"));

// В этой переменной храним параметры для выполнения фонового задания
СтруктураПараметров = Новый Структура;
СтруктураПараметров.Вставить("Дерево", ДеревоОбъект);
СтруктураПараметров.Вставить("ОтборНачалоПериода", Объект.НачалоПериода);
СтруктураПараметров.Вставить("ОтборКонецПериода", Объект.КонецПериода);

// Помещаем данные параметров в хранилище значения и пакуем их в XML строку.
XMLСтруктура = XMLСтрока(Новый ХранилищеЗначения(СтруктураПараметров, Новый СжатиеДанных(9)));

// Заполняем массив параметров фонового задания
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(XMLСтруктура);

// Вызываем запуск фонового задания.
// Ключом являеся уникальный идентификатор формы.
ФоновыеЗадания.Выполнить("ОбщийМодуль1.ВыполнитьФоновыйКод", МассивПараметров, УникальныйИдентификатор, "Вывод данных через фоновое задание");

КонецПроцедуры // ВыполнитьВФонеНаСервере

&НаКлиенте
Процедура ОжиданиеРезультатаВыполнения() Экспорт
// Задание запустилось. Ожидаем завершения.

// Переменная по которой будем знать на клиенте, что фоновое задание завершилось
ЕстьРезультат = Ложь;

// Опять же, работа с фоновыми заданиями возможна на сервере
ОжиданиеРезультатаВыполненияНаСервере(ЕстьРезультат);

Если ЕстьРезультат Тогда
ОтключитьОбработчикОжидания("ОжиданиеРезультатаВыполнения"); // Если задание выполнилось, отключаем обработчик ожидания
КонецЕсли;

КонецПроцедуры // ОжиданиеРезультатаВыполнения

&НаСервере
Процедура ОжиданиеРезультатаВыполненияНаСервере(ЕстьРезультат)

// Выполним поиск фонового задания по Уникальному идентификатору формы, Наименованию и состоянию.
СтруктураОтбора = Новый Структура("Ключ, Наименование, Состояние", УникальныйИдентификатор, "Вывод данных через фоновое задание", СостояниеФоновогоЗадания.Завершено);

МассивЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(СтруктураОтбора);

Если МассивЗаданий.Количество() Тогда
// Нужное задание найдено. Можно получать данные и обрабатывать их.

ДеревоССервера = РеквизитФормыВЗначение("Дерево", Тип("ДеревоЗначений"));

XMLССервера = ХранилищеОбщихНастроек.Загрузить("ВыполнениеФоновогоЗадания", "ВыполнениеФоновогоЗадания");
ХранилищеССервера = XMLЗначение(Тип("ХранилищеЗначения"), XMLССервера);
ДеревоССервера = ХранилищеССервера.Получить();

ЗначениеВРеквизитФормы(ДеревоССервера, "Дерево");

ЕстьРезультат = Истина;

КонецЕсли;

// Можно добавить поиск заданий Активно, ЗавершеноАварийно или Отменено. Для теста не описывал проверки :)

КонецПроцедуры // ОжиданиеРезультатаВыполненияНаСервере

&НаСервере
Процедура ОтменитьЗаданиеНаСервере()

// Выполним поиск фонового задания по Уникальному идентификатору формы, Наименованию и состоянию.
СтруктураОтбора = Новый Структура("Ключ, Наименование, Состояние", УникальныйИдентификатор, "Вывод данных через фоновое задание", СостояниеФоновогоЗадания.Активно);

МассивЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(СтруктураОтбора);

Если МассивЗаданий.Количество() Тогда
// Задание найдено. Можно его отменить.

МассивЗаданий[0].Отменить();

КонецЕсли;

КонецПроцедуры // ПроверкаВыполненияНаСервере


Код с общего модуля:

Процедура ВыполнитьФоновыйКод() Экспорт

СтруктураПараметров = XMLЗначение(Тип("ХранилищеЗначения"), Параметр).Получить();

Дерево = СтруктураПараметров.Дерево;

// Выполняем произвольный код
...
...


// Подготавливаем данные в обработку

ТЗXML = XMLСтрока(Новый ХранилищеЗначения(Дерево));

ХранилищеОбщихНастроек.Сохранить("ВыполнениеФоновогоЗадания", "ВыполнениеФоновогоЗадания", ТЗXML);

КонецПроцедуры // ВыполнитьФоновыйКод


с Уважением, dj_serega.
Помогли - Скажи спасибо! Решил сам - поделись решением!
:)

Теги:

Похожие темы (5)

Рейтинг@Mail.ru

Поиск