Разработчики, переходящие на современные версии платформы «1С:Предприятие 8.3» (начиная с 8.3.18), часто сталкиваются с обманчивым ощущением, что ключевые слова Асинх и Ждать привносят в систему полноценную многопоточность, аналогичную C# или Java. Однако при попытке выполнить тяжелые расчеты в «параллельном» режиме выясняется, что код все равно выполняется последовательно, а интерфейс замирает. Проанализируем, почему так происходит, и разберем истинное назначение асинхронности в 1С.
Рассмотрим пример кода, который часто приводит к недоумению. Программист пытается запустить две функции с тяжелыми вычислениями (циклами), ожидая, что они выполнятся одновременно:
&НаКлиенте
Асинх Процедура ВыполнитьРасчет(Команда)
Обещание1 = ТяжелыйСчет(5); // Запуск первой функции
Обещание2 = ТяжелыйСчет(5); // Запуск второй функции
Результат1 = Ждать Обещание1;
Результат2 = Ждать Обещание2;
КонецПроцедуры
&НаКлиенте
Асинх Функция ТяжелыйСчет(Множ)
М = 0;
Для Й = 1 по Множ * 1000000 Цикл
М = Й;
КонецЦикла;
Возврат Строка(ТекущаяДата());
КонецФункции
В данном примере параллельности не будет. Выясним причину: в 1С клиентское приложение работает в одном основном потоке. Когда вызывается первая функция ТяжелыйСчет, управление передается в неё. Поскольку внутри функции находится обычный цикл Для, он полностью захватывает этот единственный поток. Пока цикл не завершится, управление не вернется в вызывающую процедуру, и вторая функция даже не начнет выполняться. Платформа 1С использует модель асинхронности, схожую с NodeJS: событийно-ориентированный цикл в одном потоке.
Важно четко разделять эти понятия, чтобы эффективно проектировать систему. Рассмотрим основные отличия:
В 1С конструкции Асинх и Ждать реализуют именно асинхронность. Они предназначены для I/O-bound операций (операций ввода-вывода), где процессор большую часть времени просто ждет ответа от внешнего ресурса:
Если же вы поместите в асинхронную функцию CPU-bound задачу (математические расчеты, обработка больших массивов данных в цикле), она все равно будет выполняться синхронно и блокировать поток, так как процессору некогда «переключаться» — он занят вычислениями.
Проанализируем ситуацию с точки зрения типов данных. Любая функция, помеченная как Асинх, всегда возвращает специальный объект — Обещание (Promise). Это своего рода «квитанция» на получение результата в будущем.
Посмотрим на пример из кода выше:
Обещание1 = ТяжелыйСчет(5);
Здесь переменная Обещание1 содержит не строку с датой, а объект типа Обещание. Когда мы пишем Ждать Обещание1, мы говорим платформе: «Приостанови выполнение этой процедуры, освободи поток для других задач и вернись сюда только тогда, когда это обещание будет выполнено».
Разберем, как правильно использовать эти механизмы. Представим, что нам нужно последовательно задать пользователю два вопроса. Раньше для этого требовалось создавать сложные структуры с ОписаниеОповещения. Теперь это выглядит так:
&НаКлиенте
Асинх Процедура ОформитьЗаказ(Команда)
Ответ = Ждать ВопросАсинх("Продолжить оформление?", РежимДиалогаВопрос.ДаНет);
Если Ответ <> КодВозвратаДиалога.Да Тогда
Возврат;
КонецЕсли;
Файл = Ждать ПоместитьФайлНаСерверАсинх( , , , УникальныйИдентификатор);
// Пока файл загружается, интерфейс остается живым
КонецПроцедуры
Здесь Ждать действительно приносит пользу: пока пользователь думает над вопросом или пока файл летит на сервер, поток клиента свободен. Пользователь может свернуть окно, нажать другие кнопки (если они не заблокированы логикой), а платформа будет обрабатывать эти события.
Если перед нами стоит задача действительно параллельных вычислений, нам нужно выйти за рамки клиентского потока. Для этого в 1С существуют Фоновые задания. Они выполняются на стороне сервера в отдельных процессах операционной системы.
Схема работы для достижения параллельности должна быть следующей:
ФоновыеЗадания.Выполнить().На клиенте имитацию параллельности можно организовать с помощью метода ПодключитьОбработчикОжидания(). Если разбить одну большую задачу на мелкие порции и выполнять каждую порцию по таймеру, интерфейс не будет «замерзать», так как между порциями расчетов платформа успеет обработать нажатия кнопок и перерисовку окон.
Несмотря на отсутствие параллельности, Асинх/Ждать — это не просто «синтаксический сахар». Этот механизм значительно упрощает разработку:
Попытка...Исключение вокруг асинхронных вызовов. В старой модели с оповещениями приходилось передавать отдельный обработчик для ошибок.Для...Цикл, внутри которого вызывается асинхронная операция. Сделать это через ОписаниеОповещения было практически невозможно без рекурсии.Выясним главные правила работы с асинхронностью в 1С:
Асинх и Ждать работают в одном потоке на клиенте.ОписаниеОповещения, делающая код чище и стабильнее.