Синхронные и асинхронные методы
В рамках одного сеанса работы в 1С выполнение встроенного языка выполняется последовательно, иначе говоря синхронно. Выполнение происходит в одном потоке, синхронные методы блокируют основной поток до окончания своего выполнения.
Пример синхронного выполнения:
&НаКлиенте
Процедура Команда1(Команда)
а = 1;
б = 2;
СинхронныйМетод();
Сообщить("Окончание процедуры");
КонецПроцедуры
&НаКлиенте
Процедура СинхронныйМетод()
Сообщить("Синхронный метод");
КонецПроцедуры
Сообщение «Окончание процедуры» выведется только после выполнения процедуры СинхронныйМетод, потому что при вызове данной процедуры основной поток был заблокирован, пока не будет выполнена вызванная процедура.
Асинхронные методы не блокируют основной поток. Асинхронность в 1С реализуется с помощью очереди асинхронных задач. Основной поток выполняет задачи из этой очереди, как только сможет это сделать. Важно понимать, что асинхронность это не многопоточность. Многопоточность в 1С реализуется с помощью других механизмов.
Асинхронно - это значит не дожидаясь результата выполнения процедуры или функции.
Пример асинхронного выполнения в 1С:
&НаКлиенте
Асинх Процедура Команда1(Команда)
а = 1;
б = 2;
Ждать АсинхронныйМетод();
Сообщить("Окончание процедуры");
КонецПроцедуры
&НаКлиенте
Асинх Функция АсинхронныйМетод()
Сообщить("асинхронный метод");
КонецФункции
В примере выше сначала будет выведено сообщение «Окончание процедуры», а только потом сообщение «асинхронный метод». Так происходит, потому что сразу после вызова функции АсинхронныйМетод продолжилось выполнение кода.
Асинхронную технику можно использовать только на клиенте для реализации следующих задач:
- Работа с блокирующими окнами
- Работа с расширением работы с файлами
- Работа с расширением криптографии
- Работа с внешними компонентами
В нашем примере использовать асинхронность через Обещания, но 1С поддерживает два варианта асинхронности:
1. Асинхронность через обратные вызовы (ОписаниеОповещения)
2. Асинхронность через Обещания
ОписаниеОповещения
Асинхронность через обратные вызовы реализована в 1С с помощью объекта встроенного языка ОписаниеОповещения. Сам термин обратный вызов (call back) называется так, потому что мы сначала передаем ссылку на метод в асинхронную процедуру или функцию, а после выполнения асинхронной процедуры выполняется обратный вызов переданного метода.
Процедуры обратного вызова могут быть только на клиенте, обязательно со словом Экспорт, только в модуле формы, модуле команды или в общем модуле.
Например:
&НаКлиенте
Процедура Команда1(Команда)
//создаем описание оповещения
ОбратныйВызов = Новый ОписаниеОповещения("ОбратныйВызов", ЭтотОбъект);
//показываем предупреждение пользователю
ПоказатьПредупреждение(ОбратныйВызов, "Нажмите ОК");
Сообщить("Завершение процедуры");
КонецПроцедуры
//данная процедура будет вызвана после того как в предупреждении нажмут "ОК"
&НаКлиенте
Процедура ОбратныйВызов(ДополнительныеПараметры) Экспорт
//обязательно экспортная
Сообщить("Нажали ОК");
КонецПроцедуры
В данном примере мы сначала создаем объект встроенного языка ОписаниеОповещения. Первым параметром передаем название процедуры, которая будет вызвана после завершения асинхронного метода. Вторым - модуль, где находится данная процедура. Так как мы находимся в модуле формы и процедура обратного вызова будет расположена здесь же, то нужно указать ЭтотОбъект. Затем методом ПоказатьПредупреждение показываем пользователю предупреждение с кнопкой «ОК»:
Сразу после показа окна с предупреждением внизу будет показано сообщение «Завершение процедуры», а после нажатия на кнопку «ОК» будет выполнен обратный вызов процедуры ОбратныйВызов, которая покажет сообщение «Нажали ОК».
При использовании синхронного аналога Предупреждение основной поток был бы заблокирован до нажатия на кнопку «ОК».
Асинхронность через обещания
Обещание
Обещание - это обертка над результатом асинхронной функции. Асинхронная функция всегда возвращает объект Обещание. Обещание - это обычный объект встроенного языка 1С, его можно присвоить какой-то переменной, можно передать через параметры в другую процедуру или функцию. Но обещание нельзя передавать на сервер. Также обещание нельзя создать через конструктор, его можно получить только как результат асинхронной функции.
Объект обещание может иметь 3 состояния:
-Pending - обещание еще не завершилось, начальное состояние обещания.
-Success - обещание завершилось успешно. В обещании «завернут» результат асинхронной функции.
-Failure - в асинхронной функции было выброшено исключение, данное исключение было «завернуто» в обещание.
Оператор Ждать
Оператор Ждать позволяет получить результат функции из обещания. Параметром данного оператора может быть только объект с типом обещание. Оператор Ждать можно использовать только в процедурах и функциях, которые отмечены модификатором Асинх. А также у собственных асинхронных функций, которые возвращают обещание тоже нужно указывать модификатор Асинх.
Например:
&НаКлиенте
Асинх Процедура Команда1(Команда)
Ждать ПредупреждениеАсинх("Асинхронное предупреждение");
Сообщить("Завершение процедуры");
КонецПроцедуры
В данном примере мы используем асинхронную функцию для вызова предупреждения - ПредупреждениеАсинх. Метод ПредупреждениеАсинх вернет обещание. Чтобы получить результат данного метода используется оператор Ждать. А чтобы в процедуре Команда1 можно было использовать оператор Ждать перед ней указан модификатор Асинх.
В результате сообщение «Завершение процедуры» будет показано только после того как мы нажмем «ОК» в предупреждении. Несмотря на то что мы использовали асинхронную функцию выполнение встроенного языка не было продолжено, пока оператор Ждать не получил результат асинхронной функции.
Если вызвать асинхронное предупреждение без оператора Ждать, то сообщение и предупреждение будут показаны почти одновременно. Сразу после показа предупреждения было продолжено выполнение встроенного языка и сообщение было показано до того как мы нажали «ОК» в предупреждении:
&НаКлиенте
Процедура Команда1(Команда)
ПредупреждениеАсинх("Асинхронное предупреждение");
Сообщить("Завершение процедуры");
КонецПроцедуры
Если использовать в методе оператор Ждать, но не указать модификатор Асинх, то будет ошибка: «Оператор Ждать (Await) может употребляться только в асинхронных процедурах или функциях».
Обработка исключений
Если в асинхронной функции было выброшено исключение, то оператор Ждать позволяет получить его и корректно обработать:
&НаКлиенте
Асинх Процедура Команда1(Команда)
Обещание = ФункцияАсинх();
Попытка
Ждать Обещание;
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
&НаКлиенте
Асинх Функция ФункцияАсинх()
ВызватьИсключение "Исключение из асинхронной функции";
КонецФункции
В данном примере в асинхронной функции ФункцияАсинх было выброшено исключение. Данное исключение было получено оператором Ждать из обещания и корректно обработано через конструкцию Попытка - Исключение. В результате вместо исключения мы в сообщениях увидим текст с ошибкой: «{Обработка.Обработка1.Форма.Форма.Форма(24)}: Исключение из асинхронной функции».
Асинхронные процедуры
Асинхронной может быть как функция, так и процедура. Но асинхронная процедура не возвращает обещание и нельзя корректно обработать исключения, которые могут быть выброшены в ней. Асинхронные процедуры можно использовать как асинхронные обработчики каких-либо событий.
Важно отметить, что как в асинхронную процедуру, так и в в асинхронную функцию параметры передаются только по значению. Ключевое слово Знач перед именем параметра игнорируется.
Асинхронные методы через обещания можно использовать только начиная с версии платформы 8.3.18. Режим совместимости конфигурации не влияет.
Смотрите также:
Электронный учебник по по программированию в 1С Рекомендации по изучению программирования 1С с нуля Программное решение для сдачи и подготовки к экзаменам Программирование в 1С 8.3 с нуля - краткий самоучитель Комплексная подготовка программистов 1С:Предприятие 8.2 Сайты с уроками программирования и со справочниками Youtube-каналы с уроками программирования Сайты для обучения программированию Лекции и уроки