Пауза на платформе 1С, очень нативная и очень бережная к ресурсам

25.11.19

Разработка - Механизмы платформы 1С

Иногда необходимо установить паузу при выполнении программных алгоритмов. К сожалению, платформа 1С не имеет решения на уровне глобального контекста, поэтому приходится разработчику придумывать "костыли и велосипеды". Решения, которые "общеприняты": либо используют внешние библиотеки (VBS, WS, ping и пр.), либо нещадно используют ресурсы (бесконечный цикл и т.п.). Хочу предложить еще одно решение, основанное на механизме управляемых блокировок платформы 1С. Итак, приступим:

Скачать файлы

Наименование Файл Версия Размер
Конфигурация (cf):
.cf 13,91Kb
1
.cf 1.0.0.4 13,91Kb 1 Скачать
Расширение конфигурации (cfe)
.cfe 11,49Kb
0
.cfe 1.0.0.4 11,49Kb Скачать

Для реализации будем использовать:

1. Механизм управляемых блокировок

2. Механизм фоновых заданий и их метод: "ОжидатьЗавершенияВыполнения"

Смысл данной реализации схематично можно представить следующим образом:

Теперь к реализации:

1. Решение состоит из общего модуля и регистра сведений. (+ тестовая обработка для демонстрации работы паузы)

2. Регистр сведений необходим для реализации блокировки, по определенному условию. В нашем случае, это "НомерСеанса" (Число). Так как в одну единицу времени у информационной базы не может быть два сеанса с одинаковым номером, что позволяет нам утверждать, что пересечений по блокировкам не будет. Другими словами - одна пауза не помешает другому сеансу установить свою паузу.

3. Процедуры и функции

Процедура ВыполнитьПаузу_вСекундах(ВремяПуаузыСек,Причина="")

Параметры: 

     ВремяПаузыСек - Число - Количество секунд, на которое необходимо установить паузу

     Причина - Строка - произвольный текст, будут установлен в запись регистра сведений

Текст с пояснениями:

Процедура ВыполнитьПаузу_ВСекундах(ВремяПаузыСек,Причина="") Экспорт

	пНомерСеанса 	= НомерСеансаИнформационнойБазы(); // Номер текущего сеанса
	пИмяИнициатора 	= ИмяПользователя(); // имя пользователя
	
    // Создаем запись о паузе в регистре сведений
	МЗ = РегистрыСведений.apПауза.СоздатьМенеджерЗаписи();
	МЗ.НомерСеанса 			= пНомерСеанса;
	МЗ.ДатаНачалаПаузы 		= ТекущаяУниверсальнаяДата();
	МЗ.ДатаОкончанияПаузы	= МЗ.ДатаНачалаПаузы + ВремяПаузыСек + 3; // Необходимо значение для сборщика зависших пауз (+3 секунды на всякий случай "оверхеда")
	МЗ.Причина 				= Причина;
	МЗ.ИмяИнициатора 		= пИмяИнициатора;
	МЗ.Записать();
	
	НачатьТранзакцию(); // Вне транзакций блокировка невозможна
		Блокировка = новый БлокировкаДанных;
		Элементблокировки = Блокировка.Добавить("Регистрсведений.apПауза");
		Элементблокировки.УстановитьЗначение("НомерСеанса",пНомерСеанса);
		Элементблокировки.Режим=РежимБлокировкиДанных.Исключительный;
		Блокировка.Заблокировать(); // Установили блокировку (ни один другой сеанс не может прочесть это значение)
		
		МассивПараметров = Новый Массив;
		МассивПараметров.Добавить(пНомерСеанса);
		МассивПараметров.Добавить(МЗ.ДатаОкончанияПаузы + ВремяПаузыСек);
		
        //Запускаем фоновое задание, передаем параметр текущего номера сеанса
		ФЗ = ФоновыеЗадания.Выполнить("apПауза.сис_Пауза",МассивПараметров,,"пауза от " + пИмяИнициатора + " (" + пНомерСеанса + ")");
		
		
		Если РежимСовместимости_8_13_ИВыше() Тогда // у платформы с 8.3.13 "ОжидатьЗавершенияВыполнения", более ранняя "ОжидатьЗавершения"
			Попытка
				ФЗ = ФЗ.ОжидатьЗавершенияВыполнения(ВремяПаузыСек); // Время ожидания равно времени паузы	
			Исключение;
			КонецПопытки;
		Иначе
			Попытка
				ФЗ.ОжидатьЗавершения(ВремяПаузыСек); // Время ожидания равно времени паузы
			Исключение;
			КонецПопытки;
		КонецесЛИ;
	ОтменитьТранзакцию(); // пауза закончена, снимем блокировку
	
	МЗ.НомерСеанса = пНомерСеанса;
	МЗ.Удалить(); // Удалим запись о паузе
КонецПроцедуры

Процедура сис_Пауза(НомерСеанса,ВремяОкончанияПаузы)

Параметры: 

     НомерСеанса - Число - Номер сеанса, который ставится на паузу

     ВремяОкончанияПаузы- Дата в UTC- Когда должна закончится пауза (когда пауза больше времени ожидания на снятие блокировки)

Текст с пояснениями:

Процедура сис_Пауза(НомерСеанса,ВремяОкончанияПаузы) Экспорт
	МЗ = РегистрыСведений.apПауза.СоздатьМенеджерЗаписи();
	МЗ.НомерСеанса = НомерСеанса;
	
	Пока ТекущаяУниверсальнаяДата() < ВремяОкончанияПаузы Цикл // Для пуаз больше 20 сек (Таймаута ожидания запроса по умолчанию)
		Попытка;
			МЗ.Прочитать(); // попытка чтения заблокированной запись - здесь и возникает ожидание паузы
		Исключение;
		КонецПопытки;
	КонецЦикла;
	
КонецПроцедуры

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

Функция получения режима совместимости и версии платформы, необходима для определения какой из методов ожидания завершения использовать у фонового задания

Процедура СборщикЗависшихПауз() Экспорт
	Запрос = Новый Запрос;
	Запрос.Текст =
		"ВЫБРАТЬ
		|	apПауза.НомерСеанса КАК НомерСеанса
		|ИЗ
		|	РегистрСведений.apПауза КАК apПауза
		|ГДЕ
		|	apПауза.ДатаОкончанияПаузы < &ТекущаяУниверсальнаядата";
	запрос.УстановитьПараметр("ТекущаяУниверсальнаядата",ТекущаяУниверсальнаяДата());
	Выборка = запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		МЗ = РегистрыСведений.Пауза.СоздатьМенеджерЗаписи();
		МЗ.НомерСеанса = Выборка.НомерСеанса;
		МЗ.Удалить();
	КонецЦикла;
конецПроцедуры

Функция РежимСовместимости_8_13_ИВыше() Экспорт
	ТекРежим = Метаданные.РежимСовместимости;
	
	Если ТекРежим = Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать тогда
	 	пСис = Новый СистемнаяИнформация;
		пВерсия = пСис.ВерсияПриложения;
		пВерсия = СтрЗаменить(пВерсия,".",Символы.ПС);
		пПерваяВерсия = Число(СтрПолучитьСтроку(пВерсия,1));
		пВтораяВерсия = Число(СтрПолучитьСтроку(пВерсия,2));
		пТретьяВерсия = Число(СтрПолучитьСтроку(пВерсия,3));
	Иначе
		пВерсия	= СтрЗаменить(СтрЗаменить(Строка(ТекРежим),"Версия",""),"_",Символы.ПС);
		пПерваяВерсия = Число(СтрПолучитьСтроку(пВерсия,1));
		пВтораяВерсия = Число(СтрПолучитьСтроку(пВерсия,2));
		пТретьяВерсия = Число(СтрПолучитьСтроку(пВерсия,3));
		
	КонецЕсли;	
		
	Если пТретьяВерсия <= 12 И пВтораяВерсия <= 3 И пПерваяВерсия = 8 Тогда
		Возврат Ложь;
	Иначе
		Возврат Истина;
	КонецЕсли;
КонецФункции

Тест паузы, как видно, в реальности пауза устанавливается на больше, чем указано в значении, примерно на 0.03 секунды.

Эти 30 мил.сек. как раз затраты на реализацию и обслуживание выполнения паузы.

Текст модуля формы обработки Теста паузы

&НаСервере
Процедура ВстатьНаПаузуНаСервере()
	пТекДата = ТекущаяДата();
	мНачало = ТекущаяУниверсальнаяДатаВМиллисекундах();
		apПауза.ВыполнитьПаузу_ВСекундах(ПаузавСекундах,"Тестовая пауза");
	Результаты.ДобавитьСтроку(Формат(пТекДата,"ДФ='dd.MM.yy HH:mm:ss'") + " пауза на " + Строка(ПаузавСекундах) +" сек. выполнена за " + Формат(ТекущаяУниверсальнаяДатаВМиллисекундах()-мНачало,"ЧГ=0") + " мил.сек.");
	
КонецПроцедуры

&НаКлиенте
Процедура ВстатьНаПаузу(Команда)
	ВстатьНаПаузуНаСервере();
КонецПроцедуры

Теперь в любом месте конфигурации можно написать "apПауза.ВыполнитьПаузу_ВСекундах(5);"

 

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

На картинке видно ожидание на управляемой блокировке, что фоновое задание, ждет, когда Тонкий клиент "отпустит" ресурс.

... Протестировано на нагрузке в 50 и более сеансов.

тестировалось на платформах 8.3.12, 8.3.15 без режима совместимости и в режиме совместимости 8.3.12

Для примера приведу рабочий кейс использования такой паузы:

Дано: система расчета показателей Apdex в режиме условно реального времени. По алгоритму для расчета индекса APDEX, необходимо знать время выполнения последних 100 таких же ключевых операций. Одна и та же ключевая операция может быть выполнена одновременно несколькими пользователями.

Решение: 

1. Есть API, которая регистрирует выполнение ключевой операции в регистре сведений,

2. Регламентное задание, с периодичностью 1 раз в 60 сек стартует фоновые задания с анализом по каждому виду ключевых операции

3. Анализ по ключевой операции заключается в следующем:

   Получение последних 100 записей из регистра сведений по данной ключевой операции

   Создание таблицы значений с этими операциями

   замещение новыми операциями, если есть (получение новых операций)

   Подсчет итога по таблице

   Установка паузы в 3 секунды и далее получение новых операций, без запроса к старым

   Если нового замера по ключевой операции не поступало в течении 30 минут, то фоновое задание завершается

 

Такая реализация позволила убрать постоянный запрос к регистру с историей операций (более 10 млн. записей)

...

В файлах можно скачать расширение или конфигурацию, в которой реализован описанный выше механизм паузы.

...

А зачем вам нужна пауза в 1С?

Пауза Pause Способы программирования механизмы

См. также

Поинтегрируем: сервисы интеграции – новый стандарт или просто коннектор?

Обмен между базами 1C Администрирование СУБД Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

В платформе 8.3.17 появился замечательный механизм «Сервисы интеграции». Многие считают, что это просто коннектор 1С:Шины. Так ли это?

11.03.2024    4420    dsdred    53    

69

Как готовить и есть массивы

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

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

24.01.2024    5269    YA_418728146    25    

62

Планы обмена VS История данных

Обмен между базами 1C Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    6380    dsdred    36    

111

1С-ная магия

Механизмы платформы 1С Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    18458    SeiOkami    46    

118

Дефрагментация и реиндексация после перехода на платформу 8.3.22

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Начиная с версии платформы 8.3.22 1С снимает стандартные блокировки БД на уровне страниц. Делаем рабочий скрипт, как раньше.

14.09.2023    12069    human_new    27    

74

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    8795    YA_418728146    6    

141

Внешние компоненты Native API на языке Rust - Просто!

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Внешние компоненты для 1С можно разработывать очень просто, пользуясь всеми преимуществами языка Rust - от безопасности и кроссплатформенности до удобного менеджера библиотек.

20.08.2023    6271    sebekerga    54    

94

Все скопируем и вставим! (Буфер обмена в 1С 8.3.24)

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Рассмотрим новую возможность 8.3.24 и как её можно эффективно использовать

27.06.2023    15945    SeiOkami    31    

103
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. json 3297 25.11.19 09:21 Сейчас в теме
Как-то очень уж сложно.
Я использовал вот такой вариант

Без регистров, сборщиков пауз и т.д.

Процедура Пауза(Секунд) Экспорт
    
    ТекущийСеансИнформационнойБазы = ПолучитьТекущийСеансИнформационнойБазы();
    ФоновоеЗадание = ТекущийСеансИнформационнойБазы.ПолучитьФоновоеЗадание();
    
    Если ФоновоеЗадание = Неопределено Тогда
        Параметры = Новый Массив;
        Параметры.Добавить(Секунд);
        ФоновоеЗадание = ФоновыеЗадания.Выполнить("ОбщегоНазначенияСервер.Пауза", Параметры); // Тут указываем имя общего модуля, в котором лежит данная процедура
    КонецЕсли;
        
    Попытка
        ФоновоеЗадание.ОжидатьЗавершения(Секунд);
    Исключение
        Возврат;
    КонецПопытки;
    
КонецПроцедуры
Показать
Merkalov; MaZaHacKa_13; DrAku1a; tormozit; chebser; awk; mickey.1cx; Sibars; herfis; Xershi; +10 Ответить
2. Xershi 1474 25.11.19 09:26 Сейчас в теме
(1) единсвенный минус бсп. В самописке надо этот модуль перенести.
3. json 3297 25.11.19 09:27 Сейчас в теме
(2) создай свой модуль, добавь в него единственную процедуру из поста выше.
Это все что требуется.
Зачем БСП?
4. Xershi 1474 25.11.19 09:30 Сейчас в теме
(3) ну не модуль, а процедуру.
20. PLAstic 295 25.11.19 11:28 Сейчас в теме
(4) Я открою тайну, что любая самописка должна строиться на базе избранных подсистем БСП. Т.е. по инструкции отмечаете галками те подсистемы, что нужны, и переносите их в чистую конфу.
Иначе, если вы пишете с нуля, это изобретение целого велосипедного парка.
23. Xershi 1474 25.11.19 12:00 Сейчас в теме
(20) если конфа узкоспециализированная и БСП там не нужен, то зачем его тащить? Максимум 1-5 функций нужны.
mihuilka; Yashazz; +2 1 Ответить
28. PLAstic 295 25.11.19 12:29 Сейчас в теме
(23) В узкоспециализированной конфе наверняка есть пользователи ИБ, есть отчёты и прочее другое, что есть среди подсистем БСП. Не вижу смысла с нуля писать то же самое и более низкого качества.
30. Xershi 1474 25.11.19 12:50 Сейчас в теме
(28) ничего подобного там нет, т.к. не нужно.
vsesam80; +1 Ответить
37. vsesam80 26.11.19 07:38 Сейчас в теме
(28)Подтверждаю. Если писать к примеру конфу для учета продаж сетевиков или там учет для автомойки, БСП там на фиг не нужен.
Отчет на СКД 5 минут делается, всего их пара нужна. К чему слона тащить в багажник?
Serega-artem; +1 Ответить
38. PLAstic 295 26.11.19 09:37 Сейчас в теме
(37) Отлично, наконец-то есть примеры задач. Итак, если в конфе хоть один отчёт есть - ВариантыОтчетов. Они позволят управлять пользовательскими вариантами и шарить им их для других пользователей. Опять же, авторизация и разделение прав - УправлениеДоступом. Контроль заполнения документов, получение реквизита объекта на клиенте - БазоваяФункциональность. Выгружать данные в другие системы - ОбменДанными. Печатные формы документов - ПодключаемыеКоманды, Печать. Что-то переделали, надо массово изменить объекты - ГрупповоеИзменениеОбъектов. Какие движения делает документ - ОтчетОДвиженияхДокумента. Структура подчинённости - СтруктураПодчиненности. Накосячили при загрузке данных, задвоили элементы справочника - ПоискИУдалениеДублей. Отправить отчёт боссу на почту - РаботаСПочтовымиСообщениями.

Вы врядли сможете привести пример конфы, где не нужна БСП. Скорее всего, вы просто плохо её знаете, поэтому не понимаете, как она облегчает разработку и поддержку. И разработка с ней - это, конечно, быстрее, чем с нуля колхозить.
40. herfis 498 26.11.19 10:51 Сейчас в теме
(37) Плохой пример. Для любой учетной конфы уже имеет смысл ставить ряд подсистем БСП. Тут я с (38) полностью согласен.
С (23) я готов согласиться только в случае чего-то слишком уж специализированного. Типа микросервиса на 1С который выполняет очень узкую сервисную задачу.
41. json 3297 26.11.19 11:20 Сейчас в теме
(37) любую конфу, если она не одноразовая, потребуется дорабатывать.
Сегодня у тебя пара отчетов, через год - уже пара десятков.

Чем больше ты написал кода, тем сложнее будет подключить БСП и тем больше объектов будут написаны на велосипедных схемах.
И после того, как ты передал конфу заказчику и он в ней начал работать - то уже не будешь подключать, потому что обосновать трудозатраты на подключение БСП на поздних этапах уже не сможешь.

Но подобный подход свойственен для новичков, а также для тех, кто не дружит с БСП.
62. gaglo 27.11.19 18:37 Сейчас в теме
(41) А главное, что это "больше кода" написал не ты, а некий автор самописки и два-три его последователя, а твоих предшественника; и ты смотришь на ЭТО и думаешь: "И теперь мне ещё всё на БСП переводить?" И не то чтобы БСП тут не нужна, но... неподъёмно как-то...
5. SlavaKron 25.11.19 10:00 Сейчас в теме
(1) Возможно ли это сделать асинхронно с вызовом процедуры текущего сеанса по окончании таймаута?
8. Sibars 352 25.11.19 10:32 Сейчас в теме
(5)
Не совсем понял вопроса. В описанном случае, после ожидания паузы, процедура дальше начнет выполнять следующую строчку кода
32. SlavaKron 25.11.19 13:23 Сейчас в теме
(8) (11) В приведенном коде ожидание происходит в текущем сеансе, а не в сеансе фонового задания. Потому ожидание вешает систему на время паузы. Если делать асинхронно, ожидание следует делать в сеансе фонового задания и тогда код должен быть таким:
Процедура Пауза(Секунд) Экспорт
    
    ТекущийСеансИнформационнойБазы = ПолучитьТекущийСеансИнформационнойБазы();
    ФоновоеЗадание = ТекущийСеансИнформационнойБазы.ПолучитьФоновоеЗадание();
    
    Если ФоновоеЗадание = Неопределено Тогда
        Параметры = Новый Массив;
        Параметры.Добавить(Секунд);
        ФоновоеЗадание = ФоновыеЗадания.Выполнить("ОбщегоНазначенияСервер.Пауза", Параметры); // Тут указываем имя общего модуля, в котором лежит данная процедура
	Иначе
		Попытка
			ФоновоеЗадание.ОжидатьЗавершения(Секунд);
		Исключение
		КонецПопытки;
	КонецЕсли;
	
КонецПроцедуры
Показать
Но в таком случае мы не сможем передать управление на сервер текущего сеанса после ожидания. Проще говоря, интересно бы видеть решение типа ПодключитьОбработчикОжидания для сервера.
35. herfis 498 25.11.19 13:36 Сейчас в теме
(32)
В приведенном коде ожидание происходит в текущем сеансе, а не в сеансе фонового задания. Потому ожидание вешает систему на время паузы.

Эта задача и решалась. Пауза в текущем потоке, но которая не грузит проц. Стандартная пауза.
36. Sibars 352 25.11.19 14:34 Сейчас в теме
(32)я понял мысль. К сожалению, пока такой реализации нет, так как с сервера вызвать клиент не получится(
9. Sibars 352 25.11.19 10:39 Сейчас в теме
(1)
ОбщегоНазначенияСервер


Коммент удалил, что б не вводить людей в заблуждение.
....
Все верно, можно и так!
11. herfis 498 25.11.19 10:40 Сейчас в теме
(9) Ты не понял. Это и есть текст этой процедуры :) Ее необходимо разместить в общем модуле.
Хитрость в ожидании фоновым заданием завершения выполнения самого себя.
13. Sibars 352 25.11.19 10:44 Сейчас в теме
(11)
понял. Это и есть текст этой процедуры :) Ее необходимо разместить в общем модуле.
Хитрость в ожидани

Я понял. Но пока идет ожидание. фоновое задание молотит бесконечный цикл. вот этим кодом:

Процедура Пауза(Время) Экспорт

	ВремяЗавершения = ТекущаяДата() + Время;
	Пока ТекущаяДата() < ВремяЗавершения Цикл
	КонецЦикла;

КонецПроцедуры
15. herfis 498 25.11.19 10:48 Сейчас в теме
(13) И где ты в (1) увидел такой код? Ты таки не понял.
В (1) как раз та самая Пауза() которую надо разместить в "ОбщегоНазначенияСервер"
Там же прямо в комментарии написано: "Тут указываем имя общего модуля, в котором лежит данная процедура"
17. Sibars 352 25.11.19 11:01 Сейчас в теме
(15)
Разобрался. Ты прав.
Мой коммент (9) - чушь. Там клиентская пауза бестолковая.
Единственное, что заметил, чуть утекает память у rphost метров на 5 для каждой паузы.
Проц не грузит.
Решение элегантно)
39. tormozit 7136 26.11.19 10:41 Сейчас в теме
6. savostin.alex 83 25.11.19 10:02 Сейчас в теме
Пауза в 3 секунды:

Попытка
	Для Счетчик = 1 По 3 Цикл
	ПолучитьCOMОбъект("winmgmts:").ExecNotificationQuery("Sel ect * fr om __instancemodificationevent where TargetInstance isa 'Win32_UTCTime'").NextEvent();
	КонецЦикла;
Исключение
КонецПопытки;
7. Sibars 352 25.11.19 10:31 Сейчас в теме
(6)
Эта функция использует Com объект, будет работать, но не везде (Например в linux не "взлетит")
10. herfis 498 25.11.19 10:39 Сейчас в теме
Кстати, хороший вопрос. Кому и зачем какие паузы нужны? Мне нужны были только в пределах полусекунды, при работе с торговым оборудованием. Обходился бесконечным циклом. А три секунды и выше зачем могут понадобиться?
12. Sibars 352 25.11.19 10:42 Сейчас в теме
(10)
Такая пауза нужна, когда необходимо "подождать" событие, при этом "не потерять" значения собранных переменных. В описанном случае, что б заново не вытаскивать значения из БД.
14. herfis 498 25.11.19 10:47 Сейчас в теме
(12) Подождать какое событие?
16. Sibars 352 25.11.19 10:56 Сейчас в теме
(14)
Когда "прилетит" новый замер по api, например
18. herfis 498 25.11.19 11:04 Сейчас в теме
(16) Когда надо с какой-то периодичностью получать данные, но при этом накапливать в памяти порции? Ну, такое... Достаточно узкий случай, как по мне.
(17) Странно. Т.е. ты говоришь о том, что после двухсот пауз будет "съеден" лишний гиг?
19. Sibars 352 25.11.19 11:06 Сейчас в теме
(18)
Странно. Т.е. ты говоришь о том, что после двухсот пауз будет "съеден" лишний гиг?

Глубоко не тестировал, накинул обработку, посмотрел состояние rphost. увидел увеличение памяти, после выполнения память освободилась.
21. json 3297 25.11.19 11:35 Сейчас в теме
(10) у меня был такой случай:
есть сторонний сервис, который работает по схеме, что по первому запросу, он тебе возвращает ответ, что твой запрос взят в разработку.
а потом ты к нему обращаешься и запрашиваешь результат выполнения своего запроса.

вот тогда ты делаешь первый запрос.
потом ставишь паузу.
потом обращаешься повторно, чтобы получить результат обработки первого запроса
если пришел ответ, что запрос еще обрабатывается, то ставишь паузу и еще раз обращаешься.
herfis; user774630; Sibars; +3 1 Ответить
22. ImHunter 312 25.11.19 11:56 Сейчас в теме
(21) Мда, рецепт из категории "вредных советов".
Сервис потормозит дольше обычного - и что, потеряем данные? Ну или, в лучшем случае, затормозим обработку других тикетов.
24. Sibars 352 25.11.19 12:06 Сейчас в теме
(22)
Реализуется программно. Все что не получили ответа в течении n-времени, заново инициируем подключение и проверку.
25. ImHunter 312 25.11.19 12:12 Сейчас в теме
(24) Нафиг, я в такие игры не играю. Пишу в регистр тикеты/статусы, потом обрабатываю регистр другим потоком.
В итоге, имеем хорошо разделенную логику, имеем хорошую масштабируемость.
mivari; acanta; +2 Ответить
26. acanta 25.11.19 12:15 Сейчас в теме
(25) вы изменяете ранее записанные строки в регистре сведений (статус, время выполнения)? Или удаляете после обработки?
27. ImHunter 312 25.11.19 12:21 Сейчас в теме
(26) На последнем решении - было сразу и то, и другое. Менял статусы - это сразу.
И работало задание очистки, которое совсем старую историю вычищало.

Но это уже совсем другая история;) То бишь, оффтоп.
29. json 3297 25.11.19 12:32 Сейчас в теме
(22) задача понята неправильно - вывод сделан неверный.

Сервис не тормозит, а обрабатывает запросы асинхронно.

Сначала он твой запрос ставит в очередь на обработку, а потом ты к нему ходишь и запрашиваешь результат обработанного запроса.

Сервис государственный, если что

И в чем вредность, давай-ка разъясни
31. ImHunter 312 25.11.19 12:58 Сейчас в теме
(29) Вот сервис работает асинхронно. Пусть он даже "государственный, если что".
Ты-то почему тогда синхронно с ним работаешь?

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

Вообще, твое решение с паузами все же имеет место. Но только в одном случае - если этого ждет пользователь, вот прямо здесь и сейчас.
Для пакетной работы - лучше сразу писать по-нормальному.
mivari; PLAstic; nomad_irk; +3 Ответить
33. json 3297 25.11.19 13:28 Сейчас в теме
(31)
Ты-то почему тогда синхронно с ним работаешь?


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

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

Если тикеты отправляем массово, то такой способ может не подойти, согласен.
Но для штучных отправок - метод подходящий
42. PLAstic 295 26.11.19 13:55 Сейчас в теме
(33) Для любого количества нужно делать без тормозов в интерфейсе. Собственно, как формирование отчётов в БСП - пока крутится кругляш, ты продолжаешь работать, а как сформировался отчёт - вывелся на экран в фоне. Когда будет время, тогда и глянешь на него.
Похоже, проблема только в незнании, насколько этот процесс прост. Кстати, формирование первичного запроса, его отправка и старт фонового задания - это выполняется в один поток, т.ч. "чтобы та процедура по обработке ответа выполнилась не раньше, чем закончит выполняться процедура по отправке тикета" не актуально.
50. json 3297 26.11.19 14:46 Сейчас в теме
(42) тут же никто тебя не заставляет крутить бесконечно.

В таких случаях можно использовать другую схему:
Ты отправляешь тикет.
Один-два-три-десять раз его проверяешь - в зависимости от конкретной задачи.
Если ответ не получил - то отваливаешься.
Значит ответ на запрос придет через асинхронный поток.

Такой подход позволит тебе в некоторых частных случаях обрабатывать запрос значительно быстрее.

Если у тебя, например, стоит два асинхронных потока, из которых один отправляет тикеты, а второй загружает по ним ответы, то тебе придется дольше ждать.
А если еще в общем потоке много тикетов висят, то тебе нужно подождать пока вся очередь прогрузится.
А при синхронном варианте ты можешь быстро обработать нужный тебе тикет.
34. herfis 498 25.11.19 13:30 Сейчас в теме
(31) Ты так говоришь, как будто синхронность это что-то плохое. Асинхронность не бесплатна. Не стоит ее тащить туда, где можно без нее обойтись.
Нафига нам прорва масштабируемости, если мы точно знаем, что она не потребуется? Ну вот нафига? Очередь, воркеры, промежуточные этапы, машина состояний? Backpressure? Ради несколько раз в день дернуть "ручку"?
43. PLAstic 295 26.11.19 13:56 Сейчас в теме
(34) Ты вообще про 1С или жаву? В 1С достаточно запустить фоновое задание. Всё.
Нет тормозов в интерфейсе, пользователь продолжает работать, а не ждёт, пока "программа отвиснет".
Рекомендую почитать "стандарты и методику разработки".
https://its.1c.ru/db/metod8dev#content:1528:hdoc
https://its.1c.ru/db/edtdoc#content:10047:1
https://its.1c.ru/db/v8315doc#bookmark:dev:TI000002036
44. herfis 498 26.11.19 14:09 Сейчас в теме
(43) Я про что угодно. А здесь речь вообще не про интерфейс.
45. PLAstic 295 26.11.19 14:12 Сейчас в теме
(44) Тогда почитай ссылки, там подробнее описаны несколько строк кода, которые тебе понадобятся вместо всей этой мишуры.
46. herfis 498 26.11.19 14:18 Сейчас в теме
(45) Ты просто немного не понял, о чем речь. Проехали.
47. PLAstic 295 26.11.19 14:27 Сейчас в теме
(46) Я спросил жену (QA lead). :) Все эти термины тут не уместны.
48. herfis 498 26.11.19 14:33 Сейчас в теме
(47) Backpressure в контексте обсуждения было лишним :) Остальное в тему.
Речь про задачу (21). С чего ты вообще взял, что инициатор события пользователь/клиент?
Нафига тут асинхронность, если можно спокойно это обработать в одном потоке?
63. savostin.alex 83 24.12.19 13:19 Сейчас в теме
(10)Я делал ЭДО (Контур), одна организация продает второй, КЭП обеих организаций у сотрудника есть, нужно отправить и подписать УПД с двух сторон - продавца и покупателя. Часто подписание от покупателя не срабатывает, т.к. УПД до него дойти не успел (загруженность серверов Контур?), вставил паузу - стало значительно лучше, но все равно изредка, да "стреляет".
49. herfis 498 26.11.19 14:35 Сейчас в теме
ImHunter ведь дальше начал про регистры сведений (очереди) и обработку этой очереди отдельным потоком (воркером).
51. ImHunter 312 26.11.19 15:57 Сейчас в теме
(49) Даже если говорить не про обработку очереди, а про обработку тычков пользователя, то асинхронность тоже без особых наворотов делается.
ПодключитьОбработчикОжидания(...) + ОписаниеОповещения([для хранения каких-то переменных и задания метода обработки]) + ВыполнитьОбработкуОповещения(...) - ну и вот, этим получаем асинхронное поведение.
52. herfis 498 27.11.19 10:13 Сейчас в теме
(51) Сабж изначально про классическую паузу в текущем потоке. Иногда это самый адекватный вариант решения проблемы. Вообще не понимаю, почему вдруг про пользовательский интерфейс начали говорить. Ясен пень, пользовательский интерфейс должен быть отзывчив по максимуму.
Меня просто покоробила подача, что мол "асинхронность - наше все и всегда". Нет, не все и не всегда. Вечно народ из крайности в крайности кидает.
В частности для задачи (21), если по регламенту опрашивается какой-то сервис с асинхронным протоколом и коротким предсказуемым временем отклика, то гораздо проще использовать паузу, чем городить очередь. Если нет особых требований по пропускной способности и масштабируемости ессно.
А если и после паузы не срослось - то можно кидать эксепшн, настроив для регламента количество повторов при ошибках.
lmnlmn; json; tormozit; +3 Ответить
53. ImHunter 312 27.11.19 10:58 Сейчас в теме
(52) Синхронность в виде Пауз не приветствуется разработчиками платформы (я бы сказал, категорически не приветствуется). Это мы видим и по отсутствию некой штатной процедуры Пауза(...), и по развитию асинхронных методов.
Поэтому крайностей тут и нет. Есть либо использование методологически правильных решений, либо разные самопальные реализации Пауз.
54. json 3297 27.11.19 11:54 Сейчас в теме
(53) ну так ты приведи ссылку, где сказано, что не приветствуется.

Ты же не разработчик платформы, чтобы так заявлять.

Это просто твои предположения и не более того.
55. ImHunter 312 27.11.19 12:00 Сейчас в теме
(54) Я ведь привел свои соображения. Или ты ожидаешь, что в ИТС будет написано - не используйте решение Пауза на платформе 1С, очень нативная и очень бережная к ресурсам ?;)
56. lmnlmn 69 27.11.19 12:01 Сейчас в теме
(53) Дело не только в синхронности/асинхронности. Код превращается в дикую слабопонятную размазню при реализации асинхронности "методологически верно". Вот это больше всего парит, а не отзывчивость интерфейса и прочее.
57. ImHunter 312 27.11.19 12:08 Сейчас в теме
(56) Да, на самом деле - дело не только в синхронности/асинхронности. Еще дело в (не)умении написать методологически верно.
59. lmnlmn 69 27.11.19 12:20 Сейчас в теме
(57) На самом деле дело еще в умении применять критическое мышление, в том числе и к рекомендациям 1С а не воспринимать их как истину в последней инстанции. Еще полезно высовывать нос за рамки конфигуратора для расширения кругозора.
60. ImHunter 312 27.11.19 12:24 Сейчас в теме
(59) Высовывание носа за рамки конфигуратора - это явно не про эту тему. Она лишь в рамках конфигуратора и осуществлена.
61. lmnlmn 69 27.11.19 12:33 Сейчас в теме
(60)Как раз про эту. Чтоб понять что все может быть проще и лучше, но не в 1С, к сожалению. То что приходится вытворять, в том числе и в этой теме - дичь полная, но выбора нет. Хотя в силах разработчиков платформы его предоставить.
58. herfis 498 27.11.19 12:15 Сейчас в теме
(53) Ссылки на "авторитетов" без аргументации даже при наличии официальной позиции по этому поводу - слабый довод. А свои аргументы я привел.
(57) Писать асинхронно я умею. И даже других учил :) И было бы хорошо, чтобы разработчики платформы настолько категорически приветствовали асинхронность, что реализовали побольше "сахара" в языке на эту тему (как в других языках/фреймворках).
64. e-rogov 10 27.11.22 20:57 Сейчас в теме
немножко сократил:
Процедура Пауза(Секунд) Экспорт // &НаСервере
	#Если МобильноеПриложениеСервер Тогда
		ЧтоДелать = "???";
	#Иначе
	    ЭтоФоновоеЗадание = ПолучитьТекущийСеансИнформационнойБазы().ПолучитьФоновоеЗадание();
	    Если (ЭтоФоновоеЗадание <> Неопределено) Тогда
	        Попытка ЭтоФоновоеЗадание.ОжидатьЗавершения(Макс(1, Цел(Секунд)));
	        Исключение КонецПопытки;
	    Иначе
	        Попытка ИмяМодуля = 0/0;
	        Исключение ИмяМодуля = ИнформацияОбОшибке().ИмяМодуля; КонецПопытки;
	        ПарамПаузы = Новый Массив(); ПарамПаузы.Добавить(Макс(1, Цел(Секунд))); ЭтоФоновоеЗадание = ФоновыеЗадания.Выполнить("" + ИмяМодуля + ".Пауза", ПарамПаузы);
	    КонецЕсли;
	#КонецЕсли
КонецПроцедуры // Пауза(Секунд)
Показать

З.Ы.
ЭтоФоновоеЗадание = <<?>>ПолучитьТекущийСеансИнформационнойБазы().ПолучитьФоновоеЗадание();
(Проверка: Мобильное приложение-сервер)
на мобилке есть решение?
65. e-rogov 10 27.11.22 22:52 Сейчас в теме
Сделал универсально и для Android
Функция Пауза(Секунд = 1, Знач КлючФоновогоЗадания = Неопределено) Экспорт // &НаСервере
	Если (КлючФоновогоЗадания <> Неопределено) Тогда
		Попытка ФоновыеЗадания.ОжидатьЗавершенияВыполнения(ФоновыеЗадания.ПолучитьФоновыеЗадания(Новый Структура("Ключ", КлючФоновогоЗадания)), Секунд);
		Исключение КонецПопытки;
	Иначе
		Попытка ПарамПаузы = Новый Массив(); ПарамПаузы.Добавить(Макс(1, Цел(Секунд))); ПарамПаузы.Добавить("" + Новый УникальныйИдентификатор()); ИмяМодуля = 0/0;
		Исключение ИмяМодуля = СтрРазделить(ИнформацияОбОшибке().ИмяМодуля, ".", Истина); ИмяМодуля = ИмяМодуля[Макс(0, -1 + ИмяМодуля.ВГраница())]; НачВремя1 = ТекущаяУниверсальнаяДатаВМиллисекундах();
		КонецПопытки;
		КонтрольФоновоеЗадание = ФоновыеЗадания.Выполнить(ИмяМодуля + ".Пауза", ПарамПаузы, ПарамПаузы[1], "Пауза(" + ПарамПаузы[0] + ", " + ПарамПаузы[1] + ")");
		КонтрольФоновоеЗадание.ОжидатьЗавершенияВыполнения(ПарамПаузы[0]);
		Возврат Окр(0.001 * (ТекущаяУниверсальнаяДатаВМиллисекундах() - НачВремя1), 1, РежимОкругления.Окр15как20);
	КонецЕсли;
КонецФункции // Пауза(Секунд)
Показать
Оставьте свое сообщение