Почему порядок вывода сообщений в асинхронном коде 1С отличается от ожидаемого?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При переходе на платформу 1С 8.3.18 и использовании новых конструкций Асинх и Ждать многие разработчики сталкиваются с неочевидным поведением интерпретатора. Мы часто ожидаем, что код будет выполняться строго сверху вниз, но асинхронная модель требует иного подхода к пониманию потоков исполнения.

Разбираем механизм работы Асинх/Ждать

Основная сложность заключается в том, что Асинх и Ждать — это синтаксический сахар, который делает код похожим на синхронный, но физически он таковым не является. Давайте разберем по шагам, что происходит внутри системы при вызове асинхронной процедуры:

  1. Инициализация обещания: Когда вы вызываете метод с суффиксом Асинх (например, ВыбратьАсинх()), система не ждет завершения действия. Она немедленно возвращает объект типа Обещание.
  2. Продолжение выполнения: Если код сразу после вызова асинхронного метода не содержит ключевого слова Ждать, интерпретатор продолжает выполнять следующие строки в той же процедуре.
  3. Остановка при Ждать: Когда интерпретатор доходит до оператора Ждать, он проверяет, готово ли Обещание. Если ответ еще не получен, выполнение процедуры приостанавливается, и управление передается обратно платформе, чтобы она могла обрабатывать события интерфейса (нажатия кнопок, отрисовку окон и т.д.).

Анализ проблемного примера

Рассмотрим ваш код, чтобы понять, почему вывод сообщений кажется хаотичным:


&НаКлиенте
Асинх Процедура Команда1(Команда)
    Обещание = ОткрытьДиалог();
    Для ё = 1 По 10 Цикл
        Сообщить(ё);
    КонецЦикла;    
    Каталог = Ждать Обещание;
    Сообщить(Каталог);
КонецПроцедуры

&НаКлиенте
Асинх Функция ОткрытьДиалог()
    Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
    Обещание = Диалог.ВыбратьАсинх();
    МассивКаталогов = Ждать Обещание; 
    Возврат МассивКаталогов[0];
КонецФункции

Здесь важно помнить: вы вызываете ОткрытьДиалог(). Внутри этой функции почти сразу выполняется Ждать Обещание. В этот момент процедура ОткрытьДиалог приостанавливается, ожидая выбора пользователя. Однако выполнение Команда1 не блокируется, пока она сама не встретит свой оператор Ждать. Именно поэтому порядок операций часто зависит от того, как быстро система обрабатывает контексты выполнения.

Как правильно работать с асинхронным кодом

Чтобы избежать логических ошибок, придерживайтесь следующих правил:

Практические рекомендации

Если вам нужно, чтобы код выполнился строго после завершения диалога, обязательно используйте оператор Ждать сразу после получения Обещания:


&НаКлиенте
Асинх Процедура Команда1(Команда)
    // Ждем результат выполнения функции сразу
    Каталог = Ждать ОткрытьДиалог();
    
    // Цикл выполнится только после закрытия диалога
    Для ё = 1 По 10 Цикл
        Сообщить(ё);
    КонецЦикла;
    
    Сообщить(Каталог);
КонецПроцедуры

Таким образом, мы гарантируем, что выполнение блока кода с циклом произойдет строго после того, как пользователь сделает свой выбор. Понимание того, что Ждать — это точка «заморозки» процедуры, является ключом к написанию чистого асинхронного кода в 1С.

← На главную