С выходом платформы 1С:Предприятие 8.3.18 разработчики получили долгожданный инструмент для работы с асинхронностью. Если раньше нам приходилось строить сложные цепочки процедур, используя ОписаниеОповещения, то теперь код можно писать линейно и удобочитаемо. В этой статье мы подробно разберем, как работают новые ключевые слова Асинх и Ждать, и почему это кардинально меняет подход к разработке интерфейсных задач.
Ранее, чтобы выполнить простую последовательность действий — например, задать пользователю вопрос, а затем в зависимости от ответа выбрать файл — нам приходилось разбивать логику на три-четыре отдельные процедуры. Каждая последующая процедура вызывалась через ОписаниеОповещения. Это приводило к тому, что код становился фрагментированным, его было сложно читать и практически невозможно отлаживать. Проанализируем типичную ситуацию: логическая цепочка событий разрывается, и контекст выполнения теряется между процедурами.
Механизм Асинх/Ждать решает эту проблему, позволяя писать асинхронный код так, будто он выполняется синхронно. При этом поток управления не блокируется, и пользовательский интерфейс остается отзывчивым.
В основе новой модели лежит объект Обещание. Когда мы помечаем функцию модификатором Асинх, она всегда возвращает объект типа Обещание. Рассмотрим подробнее, что это значит:
Ждать приостанавливает выполнение текущей процедуры до тех пор, пока обещание не будет разрешено (получен результат или ошибка).Для создания асинхронного метода необходимо добавить ключевое слово Асинх перед Процедура или Функция. Разберем на примере модального диалога:
&НаКлиенте
Асинх Процедура ПроверитьСтатусИВыполнить()
Оповещение = "Вы хотите продолжить выполнение операции?";
Результат = Ждать ПоказатьВопросАсинх(Оповещение, РежимДиалогаВопрос.ДаНет);
Если Результат = КодВозвратаДиалога.Да Тогда
Сообщить("Пользователь согласился.");
// Продолжаем выполнение
КонецЕсли;
КонецПроцедуры
Обратите внимание на конструкцию Ждать ПоказатьВопросАсинх. Здесь выполнение кода в данной точке остановится, платформа "запомнит" состояние и вернет управление интерфейсу. Когда пользователь нажмет кнопку в диалоге, выполнение возобновится со следующей строки.
Платформа 8.3.18 и последующие версии предоставляют асинхронные аналоги для большинства интерактивных методов. Рассмотрим основные из них:
ПоказатьВопросАсинх() — замена ПоказатьВопрос().ОткрытьФормуАсинх() — позволяет дождаться закрытия формы и получить результат.ПоказатьПредупреждениеАсинх().НачатьПомещениеФайлаНаСерверАсинх(), НачатьПолучениеФайловАсинх() и другие.Одним из самых больших преимуществ нового подхода является возможность использования стандартных блоков обработки ошибок. В старой модели с ОписаниеОповещения перехват ошибок внутри обратного вызова был крайне затруднен. Теперь же мы можем обернуть асинхронный вызов в обычную Попытка.
Выясним, как это выглядит на практике:
&НаКлиенте
Асинх Процедура ЗагрузитьФайлНаСервер()
Попытка
РезультатЗагрузки = Ждать НачатьПомещениеФайлаНаСерверАсинх( , , ПутьКФайлу);
Сообщить("Файл успешно загружен: " + РезультатЗагрузки.Адрес);
Исключение
Сообщить("Произошла ошибка при загрузке: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Раньше реализация асинхронного цикла (например, последовательная обработка массива файлов с запросом подтверждения на каждом шаге) требовала сложнейшей рекурсии. Теперь мы можем использовать стандартные операторы Для или Для Каждого. Проанализируем пример последовательной обработки:
&НаКлиенте
Асинх Процедура ОбработатьСписокФайлов(МассивПутей)
Для Каждого ТекущийПуть Из МассивПутей Цикл
ТекстВопроса = "Обработать файл " + ТекущийПуть + "?";
Ответ = Ждать ПоказатьВопросАсинх(ТекстВопроса, РежимДиалогаВопрос.ОКОтмена);
Если Ответ = КодВозвратаДиалога.Отмена Тогда
Прервать;
КонецЕсли;
// Логика обработки файла
КонецЦикла;
КонецПроцедуры
Такой код выглядит чисто, логично и легко читается любым разработчиком, даже если он не знаком с тонкостями асинхронного программирования.
Важно помнить о нескольких критических моментах при использовании Асинх/Ждать:
Асинх не создает новый поток выполнения (Thread). Весь код по-прежнему работает в одном основном потоке 1С. Это "кооперативная многозадачность", которая позволяет платформе переключаться между задачами, пока ожидается ответ от пользователя или системы.Ждать стек вызовов может "обрезаться" или выглядеть иначе, так как технически это уже новый сеанс выполнения в рамках того же процесса.Если в вашей конфигурации активно используется ОписаниеОповещения, не обязательно переписывать всё сразу. Объект Обещание имеет метод Тогда(), который позволяет связать асинхронный вызов со старым механизмом. Однако для нового кода рекомендуется использовать исключительно Асинх, так как это значительно снижает вероятность ошибок "потери контекста" и упрощает сопровождение программного продукта.
Подводя итог, можно сказать, что внедрение синхронной асинхронности — это большой шаг навстречу современным стандартам разработки (схожим с JavaScript и C#). Это делает разработку на 1С более приятной, а код — надежным.