Промисэз, промисэз. Асинхронность и многопоточность

08.11.22

Разработка - Универсальные функции

В 1С появились методы, позволяющие писать код без "ОписанийОповещений". Отличная новость!

"Promises, promises" группы Naked eyes

 

 

Я уверен, что именно эта песня играла, когда выбирался подход для реализации асинхронности в 1С.

Распространённое заблуждение - смешивание понятий асинхронных процедур и функций и многопоточности. Вот реализация асинхронных процедур:

&НаКлиенте 
Асинх Процедура КопируемыйФайлНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)

Диалог    = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Обещание  = Диалог.ВыбратьАсинх();

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

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

 

&НаКлиенте 
Асинх Процедура ЗапуститьКопированиеФайла(Команда)

ИмяКопируемогоФайла                = РазложитьПолноеИмяФайла(КопируемыйФайл).Имя; 
ОбещаниеСкопироватьФайл            = КопироватьФайлАсинх(КопируемыйФайл, Каталог + "\"+ ИмяКопируемогоФайла);
ОбещаниеПредупреждения             = ПредупреждениеАсинх("Файл копируется.", 1); 

Попытка
	Ждать ОбещаниеСкопироватьФайл;
Исключение                 
	Ждать ОбещаниеПредупреждения;  
	Сообщить(ОписаниеОшибки()); 
	Возврат;
КонецПопытки; 

Ждать ОбещаниеПредупреждения;  
ПредупреждениеАсинх("Файл скопирован."); 

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

Асинхронность проще воспринимать как нарезанный хлеб, который вы положили под матрас и ушли по своим делам, а когда захотели сухарей, то заглянули под него. С одним лишь отличием, что в этом матрасе есть вложенные матрасы :) Для многопоточной работы на клиенте мы можем использовать объект встроенного языка "Поток", доступный на клиенте:

&НаКлиенте 
Асинх Процедура ЗапуститьКопированиеФайла(Команда)
ИмяКопируемогоФайла                = РазложитьПолноеИмяФайла(КопируемыйФайл).Имя; 

ИсполняемыйКодПотокаКопирования        = "Ждать КопироватьФайлАсинх(КопируемыйФайл, Каталог + ""\""+ ИмяКопируемогоФайла)";
Идентификатор                          = Новый УникальныйИдентификатор();
ИдентификаторОбещанияПотокаКопирования = Новый Поток(ИсполняемыйКодПотокаКопирования,Идентификатор); 

//Какой-то код.

//А тут нам точно нужен результат.
Пока НЕ(ОбещаниеПотокаИсполнено(ИдентификаторОбещанияПотокаКопирования)) Цикл
КонецЦикла;

Результат = ОбещаниеПотока(ИдентификаторОбещанияПотокаКопирования);

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

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

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

&НаКлиенте
Процедура УвеличитьПоЧислуФоновыхЗаданий(Команда) 
	
	СброситьСчётчикНаСервере();
	ФоновоеЗадание = УвеличитьПоЧислуФоновыхЗаданийНаСервере(); 
	ОповещениеОПрогрессеВыполнения = Новый ОписаниеОповещения("ПрогрессВыполнения", ЭтотОбъект);
	НастройкиОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
	НастройкиОжидания.ВыводитьОкноОжидания = Ложь;
	НастройкиОжидания.ОповещениеОПрогрессеВыполнения = ОповещениеОПрогрессеВыполнения;
	
	Обработчик = Новый ОписаниеОповещения("ПослеЗаписиЗагружаемыхДанныхОтчет", ЭтотОбъект);
	ДлительныеОперацииКлиент.ОжидатьЗавершение(ФоновоеЗадание, Обработчик, НастройкиОжидания);
	
КонецПроцедуры 

&НаСервере
Функция УвеличитьПоЧислуФоновыхЗаданийНаСервере()  
	
	ФЗ =	ВыполнитьПроцедуруМногопоточно();
	
	 Возврат ФЗ;  
	 
КонецФункции

&НаСервере
Функция ВыполнитьПроцедуруМногопоточно()
		
	ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(ЭтаФорма.УникальныйИдентификатор);
	ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = 'ТестированиеМногопоточности'");
	ПараметрыВыполнения.ЗапуститьВФоне = Истина;
	
	ПараметрыМетода = Новый Соответствие(); 
	
	Для Итератор = 1 По ЧислоФоновыхЗаданий Цикл
		МассивИтераторов = НОвый Массив();
		МассивИтераторов.Добавить(Итератор);  
		//ключ-не важен, параметры по порядку
		ПараметрыМетода.Вставить("ЗадержкаСекунд" + Итератор, МассивИтераторов);
	КонецЦикла;
	
	ФоновоеЗадание = ДлительныеОперации.ВыполнитьПроцедуруВНесколькоПотоков("ТестированиеСчетчика.ИнкрементироватьАсинх", 
		ПараметрыВыполнения, ПараметрыМетода);
		
	Возврат ФоновоеЗадание;
	
КонецФункции

&НаКлиенте
Процедура ПослеЗаписиЗагружаемыхДанныхОтчет(ФоновоеЗадание, ДополнительныеПараметры) Экспорт
	
	Если ФоновоеЗадание = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	Если ФоновоеЗадание.Статус = "Выполнено" Тогда
		
	КонецЕсли;
	
	Если ФоновоеЗадание.Статус = "Ошибка" Тогда   
		
	КонецЕсли;
	
КонецПроцедуры

 &НаКлиенте
Процедура ПрогрессВыполнения(Результат, ДополнительныеПараметры) Экспорт
	
	Если Результат.Статус = "Выполняется" Тогда
		Прогресс = ПрочитатьПрогресс(Результат.ИдентификаторЗадания);
		Если Прогресс <> Неопределено Тогда  
			СчетчикВыполнения = СчетчикВыполнения + Число(Прогресс.Текст);

			Сообщить(СчетчикВыполнения);
		КонецЕсли;
	КонецЕсли;
КонецПроцедуры 

&НаСервереБезКонтекста
Функция ПрочитатьПрогресс(ИдентификаторЗадания)
	Возврат ДлительныеОперации.ПрочитатьПрогресс(ИдентификаторЗадания);
КонецФункции

И в общем модуле:

Процедура ИнкрементироватьАсинх(ЗадержкаСекунд) Экспорт
	  
	  Если ЗадержкаСекунд  > 5  Тогда
		  ЗадержкаСекунд = 1;
	  КонецЕсли;
	  Генератор = НОвый ГенераторСлучайныхЧисел;
	  apПауза.ВыполнитьПаузу_ВСекундах(1,"Тестовая пауза"); 
	  ДлительныеОперации.СообщитьПрогресс(0,
	  1);
	  
КонецПроцедуры            
  

Осталось подождать, чтобы объект "Поток" перестал быть плодом воображения, Всем отличного дня!

Юмор асинхронность многопоточность

См. также

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

Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.

23.06.2024    11391    bayselonarrend    21    

162

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

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

21.05.2024    28073    dimanich70    83    

151

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

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

06.10.2023    26088    SeiOkami    48    

136

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

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

28.08.2023    17482    YA_418728146    8    

170

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    4586    76    progmaster    11    

4

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

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

27.06.2023    31331    SeiOkami    33    

117
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. gybson 08.11.22 15:54 Сейчас в теме
А откуда инфо, что ожидание не запускает отдельный поток, ведь текущий поток не прерывается.
2. пользователь 08.11.22 21:43
Сообщение было скрыто модератором.
...
3. FilatovRA 174 08.11.22 21:45 Сейчас в теме
(1) Если я правильно понял вопрос, то схема выглядит следующим образом(пишу на абстракциях): КопироватьФайлАсинх() → отправляет запрос на копирование в программу, которая занимается копированием, в ответ получает токен джоба. ЖДАТЬ - по токену бесконечно спрашивает программу копирования готов ли результат. Т.е. поток не создаётся, выделяется память для токена и всё.
4. gybson 09.11.22 09:05 Сейчас в теме
(3) Вызвать асинхронный метод платформы можно только внутри асинхронной процедуры, которая и будет фактически отдельным потоком.
5. FilatovRA 174 09.11.22 09:21 Сейчас в теме
(4) Вот статья на эту тему. Ключевое слово Асинх у процедуры как раз и создаёт её связь при интерпретации с механизмом "Ждать". Т.е. это указатель интерпретатору что в процедуре включена возможность хранения токена для "Ждать".
Оставьте свое сообщение