Предисловие
Мне было дано задание, в конфигурации: «Управление IT-Отделом 8» поднять минимальную версию совместимости платформы с `8.3.17` на `8.3.21`, данная задача выполняется не сложно, но у меня возник вопрос: «Что интересного принесло поднятие платформы для разработчиков?». Мой глаз зацепил новый функционал асинхронной разработки, а именно «Асинх-Ждать». Если сказать честно, я никогда его до этого момента не использовал в 1С, так как работа почти всегда велась с версиями ниже 8.3.18, да и если посмотреть код БСП, даже последних (на момент написания статьи) данный механизм используется редко.
Что именно привлекло мое внимание в механизме «Асинх-Ждать»
Если вы 1С разработчик со стажем, уверен вы застали времена, когда использование синхронных методов и модальных окон было обычной практикой, никто не видел в этом проблем, и в один момент 1С заявила о том, что синхронные методы — это плохо, предложив использовать вместо обычных синхронных методов асинхронные аналоги, в виде описаний оповещений
Было:
&НаКлиенте Процедура МояПроцедура() Товар = "Яблоки"; Вес = 0; Если ВвестиЧисло(Вес) Тогда Предупреждение(Товар + ": " + Вес); // прочий код... КонецЕсли; КонецПроцедуры
Стало:
&НаКлиенте Процедура МояПроцедура() Товар = "Яблоки"; Вес = 0; ДополнительныеПараметры = Новый Структура(); ДополнительныеПараметры.Вставить("Товар", Товар); ОписаниеОповещения = Новый ОписаниеОповещения("МояПроцедураЗавершение", ЭтотОбъект, ДополнительныеПараметры); ПоказатьВводЧисла(ОписаниеОповещения, Вес); КонецПроцедуры &НаКлиенте Процедура МояПроцедураЗавершение(Вес, ДополнительныеПараметры) Экспорт Товар = ДополнительныеПараметры.Товар; Если Вес <> Неопределено Тогда ОписаниеОповещения = Новый ОписаниеОповещения("МояПроцедураЗавершениеЗавершение", ЭтотОбъект, ДополнительныеПараметры); ПоказатьПредупреждение(ОписаниеОповещения, Товар + ": " + Вес); КонецЕсли; КонецПроцедуры &НаКлиенте Процедура МояПроцедураЗавершениеЗавершение(ДополнительныеПараметры) Экспорт Товар = ДополнительныеПараметры.Товар; // прочий код... КонецПроцедуры
На данном примере видно, насколько сильно увеличилась сложность восприятия кода, а представьте, что случилось с большими модулями? Они превратились в сложночитаемые наборы описаний оповещений (для интереса посмотрите на клиентскую часть РМК в типовых конфигурациях). Однозначно, инструмент описания оповещений очень полезен, как и в других языках (например, в JavaScript - callback), но обязательство, которое поставила 1С перед разработчиками, заставило хорошенько усложнить модули.
И в версии 8.3.18, когда все давно привыкли к "аду коллбэков", в "игру" вступает новый механизм «Асинх-Ждать», который призван вернуть понятную, простую читаемость кода, снизить когнитивную нагрузку читателя, пример:
&НаКлиенте Асинх Процедура МояПроцедура() Товар = "Яблоки"; Вес = 0; Вес = Ждать ВвестиЧислоАсинх(Вес); Если Вес <> Неопределено Тогда ПредупреждениеАсинх(Товар + ": " + Вес); // прочий код... КонецЕсли; КонецПроцедуры
Почему происходят такие резкие перемены требований
Основная причина – Веб-Клиент 1С. Браузер – это современный инструмент, которым пользуются большее количество обладателей электронных гаджетов, поэтому 1С обязана работать в нем, но браузеры диктуют свои стандарты под которые необходимо подстраиваться, конкретно в данной ситуации все вопросы связанные с модальными окнами и синхронным кодом напрямую связан с запретами использования таких инструментов внутри современных браузеров.
Позволяют ли эти конструкции выполнять код одновременно (в несколько потоков)
Начнем с определения. Многопоточность - это концепция, при которой программа может выполнять несколько потоков кода одновременно. Каждый поток может выполняться независимо от других, что позволяет более эффективно использовать ресурсы компьютера и повышает отзывчивость программы, пример многопоточности в JAVA:
Но, 1С так не работает. Важно отметить, что асинхронность в 1C не подразумевает многопоточность. Так-как 1С является "условно" однопоточным языком (на основании наших исследований)
ИТС по этому поводу ничего не говорит, но чтобы доказать данное утверждение достаточно запустить Process Explorer и пытаться нагрузить её любыми операциями на встроенном языке, можно увидеть что грузится только один поток. Некоторые утверждают, что можно добиться работы двух потоков путем использования встроенного браузера "WebKit", но даже если нагрузить встроенный браузер (например бесконечным циклом на JS) задачи помещаются в стек одного потока.
Асинхронность в 1С не ускоряет выполнение кода?
Асинхронность призвана избавлять процессор от ожиданий, например пока 1С ждет ответ от сайта, в этот момент может выполняться другая задача из стека, это действительно дает прирост скорости. Но, на момент написания статьи, в большинстве новых конструкций с окончанием "Асинх", не дают никакого ускорения - это синтаксический сахар (удобство написания кода, примеры показаны вначале статьи).
Никто не знает, как работает 1с изнури, ясно лишь одно, что 1С – стековый язык, соответственно все операции он добавляет в «стопку» на верх стека, затем выполняет операции одна за другой, поэтому даже когда создается эффект «многопоточности», в любом случае на клиентской части 1С всё ставит в очередь и одновременно выполняться ничего не будет, только по одной операции (за исключением операций которые обрабатывает не 1С, например подготовка ответа от сервера при использовании http запроса, в таком случае 1С возьмет другую операцию на выполнение и не будет «простаивать»).
Для доказательства утверждений выше, покажем классическую схему работы "event loop" в JavaScript, для стековых языков схема будет похожей, поэтому сразу перекладываем на 1С:
Что будет если в стеке окажется тяжелая синхронная операция? На каринке ниже показано, что в этот момент мы не можем ничего нажать в интерфейсе, видим значок загрузки возле курсора.
А если метод будет асинхронный? В таком случае задача будет разделена на две части, и пока напрягается процессоры удаленного сервера, наш процессор выполняет другие операции
Наверное, этой информации достаточно для того чтобы убедиться в том, что просто дописать процедуре ключевое слово "Асинх" не отправит операцию в другой поток, а просто поставит в очередь.