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

08.11.22

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

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

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

 

 

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

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

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

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

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

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

 

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

См. также

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

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

23.06.2024    7911    bayselonarrend    20    

156

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

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

21.05.2024    21037    dimanich70    81    

145

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

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

06.10.2023    24033    SeiOkami    48    

135

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

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

28.08.2023    15088    YA_418728146    7    

169

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

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

2 стартмани

22.08.2023    3668    57    progmaster    8    

4

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

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

27.06.2023    26208    SeiOkami    32    

114
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
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) Вот статья на эту тему. Ключевое слово Асинх у процедуры как раз и создаёт её связь при интерпретации с механизмом "Ждать". Т.е. это указатель интерпретатору что в процедуре включена возможность хранения токена для "Ждать".
Оставьте свое сообщение