При переходе на платформу 1С 8.3.18 и использовании новых конструкций Асинх и Ждать многие разработчики сталкиваются с неочевидным поведением интерпретатора. Мы часто ожидаем, что код будет выполняться строго сверху вниз, но асинхронная модель требует иного подхода к пониманию потоков исполнения.
Основная сложность заключается в том, что Асинх и Ждать — это синтаксический сахар, который делает код похожим на синхронный, но физически он таковым не является. Давайте разберем по шагам, что происходит внутри системы при вызове асинхронной процедуры:
Асинх (например, ВыбратьАсинх()), система не ждет завершения действия. Она немедленно возвращает объект типа Обещание.Ждать, интерпретатор продолжает выполнять следующие строки в той же процедуре.Ждать, он проверяет, готово ли Обещание. Если ответ еще не получен, выполнение процедуры приостанавливается, и управление передается обратно платформе, чтобы она могла обрабатывать события интерфейса (нажатия кнопок, отрисовку окон и т.д.).Рассмотрим ваш код, чтобы понять, почему вывод сообщений кажется хаотичным:
&НаКлиенте
Асинх Процедура Команда1(Команда)
Обещание = ОткрытьДиалог();
Для ё = 1 По 10 Цикл
Сообщить(ё);
КонецЦикла;
Каталог = Ждать Обещание;
Сообщить(Каталог);
КонецПроцедуры
&НаКлиенте
Асинх Функция ОткрытьДиалог()
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Обещание = Диалог.ВыбратьАсинх();
МассивКаталогов = Ждать Обещание;
Возврат МассивКаталогов[0];
КонецФункции
Здесь важно помнить: вы вызываете ОткрытьДиалог(). Внутри этой функции почти сразу выполняется Ждать Обещание. В этот момент процедура ОткрытьДиалог приостанавливается, ожидая выбора пользователя. Однако выполнение Команда1 не блокируется, пока она сама не встретит свой оператор Ждать. Именно поэтому порядок операций часто зависит от того, как быстро система обрабатывает контексты выполнения.
Чтобы избежать логических ошибок, придерживайтесь следующих правил:
Асинх, содержащая Ждать, может быть прервана. Не рассчитывайте на неизменность состояния переменных между двумя операторами Ждать, если эти переменные зависят от внешнего контекста формы.Ждать сразу после вызова.Обещания, а не на визуальный порядок строк.Если вам нужно, чтобы код выполнился строго после завершения диалога, обязательно используйте оператор Ждать сразу после получения Обещания:
&НаКлиенте
Асинх Процедура Команда1(Команда)
// Ждем результат выполнения функции сразу
Каталог = Ждать ОткрытьДиалог();
// Цикл выполнится только после закрытия диалога
Для ё = 1 По 10 Цикл
Сообщить(ё);
КонецЦикла;
Сообщить(Каталог);
КонецПроцедуры
Таким образом, мы гарантируем, что выполнение блока кода с циклом произойдет строго после того, как пользователь сделает свой выбор. Понимание того, что Ждать — это точка «заморозки» процедуры, является ключом к написанию чистого асинхронного кода в 1С.