Полный синтаксис вызовов методов, получения и установки свойств:
В документации 1С на странице https://its.1c.ru/db/v8321doc#bookmark:dev:TI000001509 описан синтаксис асинхронной работы с компонентами, но тестируя свою компоненту, мне пришлось опытным путем выявлять, какие параметры используются при получении, установке свойства и вызове метода, в основном в первом варианте работы с помощью обратного вызова. Дело в том, что у Вас может стоять далеко не последний релиз версии 8.3, а способ вызова через Обещания появился лишь начиная с 18 релиза этой версии платформы. Итак:
- Перед Асинхронным вызовом, любым, создаем Оповещение объект типа ОписаниеОповещения, конструктор Оповещения описан в Синтакс-помощнике, но там не совсем четко указано, что стоит, а что нет заполнять.
- Пример правильного заполнения для варианта Получения свойства:
Оповещение=Новый ОписаниеОповещения("ОбработкаЧтенияСвойства",ЭтаФорма,ПараметрыСвойства,"ОбработкаАсинхронногоВызоваОшибка",ЭтаФорма);
Где:
-
ОбработкаЧтенияСвойства - процедура обратного вызова, при получении результата свойства. Имеет такой синтаксис
&НаКлиенте Процедура ОбработкаЧтенияСвойства(Значение,ПараметрыСвойства) Экспорт КонецПроцедуры
Где:
-
Значение - переменная с результатом чтения свойства.
-
ПараметрыСвойства - структура, в которой мы можем получить, например ИмяСвойства, которое было передано перед созданием ОписанияОповещения, например:
ПараметрыСвойства=Новый Структура("Ключ",ИмяСвойства);
-
- ЭтаФорма - контекст, в котором находится обработчик (текущая форма)
- ПараметрыСвойства - Структура, в которой можно передать Ключ и другие параметры, необходимые для обработки полученного свойства.
- ОбработкаАсинхронногоВызоваОшибка - процедура обратного вызова, если сгенерировано исключение или отказ компоненты на запрос по получению/установке свойства, или вызову метода. Она может быть одна для всех вызовов, синтаксис обработчика следующий:
&НаКлиенте Процедура ОбработкаАсинхронногоВызоваОшибка(Знач ИнформацияОбОшибке, СтандартнаяОбработка = Истина, ДополнительныеПараметры = Неопределено) Экспорт СтандартнаяОбработка=Ложь; КонецПроцедуры
Где:
-
ИнформацияОбОшибке - объект с типом ИнформацияОбОшибке, который содержит информацию об ошибке.
-
СтандартнаяОбработка - если мы сами хотим обработать исключение, то должна быть установлена в Ложь.
-
ДополнительныеПараметры - структура с дополнительными параметрами при ошибке.
-
-
ЭтаФорма - то же самое, контекст, в котором обработчик ошибок находится.
-
-
Пример Оповещения при установке Свойства:
Оповещение=Новый ОписаниеОповещения("ОбработкаУстановкиСвойства",ЭтаФорма,ПараметрыСвойства,"ОбработкаАсинхронногоВызоваОшибка",ЭтаФорма);
Отличия от предыдущего описания в том, что данный обработчик установки свойства имеет такой синтаксис:
Процедура ОбработкаУстановкиСвойства(ПараметрыСвойства) Экспорт КонецПроцедуры
Где в ПараметрыСвойства мы можем получить как имя свойства, так и его значение, которое передавалось, если озаботились передачей сих ранее.
-
Пример Оповещения перед вызовов методов компоненты:
Оповещение=Новый ОписаниеОповещения("ОбработкаВыполненияМетода",ЭтаФорма,ПараметрыМетода,"ОбработкаАсинхронногоВызоваОшибка",ЭтаФорма);
Где:
-
ОбработкаВыполненияМетода - имя процедуры-обработчика обратного вызова. Имеет следующий синтаксис:
&НаКлиенте Процедура ОбработкаВыполненияМетода(РезультатМетода,ПараметрыМетода,ДополнительныеПараметры) Экспорт КонецПроцедуры
Где:
-
РезультатМетода - произвольного типа, значение, которое возвращается методом компоненты, если он возвращает значение.
-
ПараметрыМетода - параметры метода, которые были переданы в компоненту. Возможно часть параметров, может быть изменены самой компонентой.
-
ДополнительныеПараметры - структура дополнительных параметров, что была передана асинхронным вызовом метода.
-
- ЭтаФорма - контекст, в котором находится обработчик (текущая форма)
- ПараметрыМетода - Структура, в которой можно передать Имя метода и другие параметры, необходимые для обработки результата вызова метода.
-
ОбработкаАсинхронногоВызоваОшибка - обработчик исключений компоненты. Синтаксис уже описан.
-
ЭтаФорма - то же самое, контекст, в котором обработчик ошибок находится.
-
- Пример правильного заполнения для варианта Получения свойства:
-
Получение/передача значения свойства и выполнение методов компоненты способом "Обратного вызова" уже описаны в документации, я просто их перечислю в правильном синтаксисе:
-
Аддон.НачатьПолучение<ИмяСвойства>(Оповещение)
-
Аддон.НачатьУстановку<ИмяСвойства>(Оповещение,Значение)
-
Для вызовов методов без параметров: Аддон.НачатьВызов<ИмяМетода>(Оповещение)
-
Для вызовов методов с параметрами: Аддон.НачатьВызов<ИмяМетода>(Оповещение,Параметр1,...)
-
-
Получение/передача значения свойства и выполнение методов компоненты через Обещание также уже описаны в документации. Следует отметить, что все процедуры и функции, содержащие эти инструкции, должны быть обозначены оператором Асинх перед названием процедуры и функции 1С. Перечислим:
- Получение свойства:
Значение=Ждать Аддон.Получить<ИмяСвойства>Асинх();
-
Установка свойства:
Результат=Ждать Аддон.Установить<ИмяСвойства>Асинх(Значение);
-
Выполнение метода компоненты:
Значение=Ждать Аддон.<ИмяМетода>Асинх(); // функция без параметров, возвращает тип "РезультатАсинхВызоваВнешнейКомпоненты" Ждать Аддон.<ИмяМетода>Асинх(); // процедура без параметров Значение=Ждать Аддон.<ИмяМетода>Асинх(ЗначениеПараметра1,...); // функция с явным перечислением параметров, возвращает "РезультатАсинхВызоваВнешнейКомпоненты"
- Получение свойства:
Особенности использования асинхронных вызовов свойств и методов внешних компонент:
- Отличия взаимодействия 1С с компонентой в режиме синхронной и асинхронной работы. Отличия в работе асинхронного режима от синхронного все-таки есть. Они проявляются в кешировании имени свойства на стороне 1С при асинхронных вызовах. Т.е. при обычной работе с компонентой, прежде чем получить или установить Значение по имени свойства, 1С всегда выполняет метод компоненты FindProp. Это позволяет использовать динамический набор свойств в случае, если компонента этого хочет. Например, в одном из случаев реализации моей компоненты, есть метод Сортировать (Sort), который сортирует свойства по имени. Т.е. порядок Свойств может поменяться. И для обычных вызовов это приемлемо и позволяет осуществлять определенную гибкость в реализации. В асинхронных вызовах получения/установки свойств - если свойство хотя бы раз уже было получено, то 1С сразу выполняет методы GetValue или SetValue с заранее полученными номерами этих свойств. Зачем это сделано, я не знаю, но может привести к серьезным проблемам, когда вы ждете одно свойство, а получаете или устанавливаете другое... Поэтому для компонент, динамически меняющих состав свойств - асинхронные вызовы не рекомендуются. То же касается и методов FindMethod. Только мне сложно представить, что кто-то будет реализовывать динамический набор методов, но лично я реализовывал разные наборы методов в зависимости от того, какой вложенный в компоненте объект использовался. Но остановился на том, что номера методов лучше не менять ни в каком режиме.
- Рассмотрим поведение 1С при разных вариантах реализации Асинхронных вызовов. Что я выявил:
- Все знают, что неудобно разрабатывать в режиме "Обратного вызова" проекты, из-за загромождения лишними функциями (Callback) и операторами создания Оповещений. Но, оказывается, так все же надежнее и гибче эти методы выполняются.
- Во первых в режиме Модальности - или для УФ - это будет по факту режим блокирования родительского окна, после того как мы запустим функцию работы компонентой в режиме "обратного вызова", она сразу начнется исполняться, не дожидаясь выхода и закрытия модального окна. Это выявлено как в УФ, так и в обычных формах.
- Во вторых, мы можем динамически формировать код, который хотим выполнить, если мы заранее не знаем, какое свойство или метод мы будем выполнять и используем операторы Выполнить или Вычислить.
- Способ работы со свойствами и методами компонент в режиме формирования Обещаний, соблазнителен на первый взгляд из-за краткости написания кода, но имеет недостатки:
- В модальных вызовах форм (путем блокировки родительского окна для УФ), все методы и свойства компонент, вызываемые через обещания с помощью оператора Ждать, не начнут выполняться, пока не закроется модальное окно и не освободит родительское для принятия оконных сообщений.
- Мы через обещания можем работать только с явно заданными свойствами и методами внешних компонент. Т.е. не работают операторы Выполнить и Вычислить, что ограничивает разработчика в некоторых действиях, например, когда нам нужно протестировать работу неизвестной компоненты в автоматическом режиме. Или мы не можем делать код, в котором должна будет на место драйвера подгружаться пока неизвестная нам компонента с неизвестными свойствами.
- Все знают, что неудобно разрабатывать в режиме "Обратного вызова" проекты, из-за загромождения лишними функциями (Callback) и операторами создания Оповещений. Но, оказывается, так все же надежнее и гибче эти методы выполняются.
Асинхронность и параллельность, то ли мы купили:
Когда мы слышим Асинхронность, мы не всегда понимаем, что стоит за этим словом и как это работает в системе. Многие считают, что это освобождает Основной поток и дает параллельность в выполнении задач. На самом деле это не так, это не имеет никакого отношения к реальной поточной работе. Реальный параллелизм возникает, когда мы запускаем какое-то задание в Фоновом процессе на Сервере. Там оно выполняется в отдельной среде без выделения ему ресурсов как для отдельной задачи, но по факту это задача со своей таблицей управления и набором регистров. Система переключает не только процессы, но и потоки между процессами, выделяя каждому определенные кванты времени, переключаясь между ними, обеспечивая баланс между переключениями меж самих процессов и между потоками этого процесса. И в целом эти все потоки выполняются почти параллельно. Но есть в системе старый способ обеспечивать параллельность в работе, который пришел к нам из Windows 3.0, с помощью эмуляции параллелизма через очередь сообщений в Главные окна. Принцип работы заключается в том, что система выполняет какое-то задание через очередь сообщений и затем после возвращает управление системе, ожидая следующего задания. Так это работает и сейчас для взаимодействия с пользователем через GUI в окнах. Асинхронный режим, который реализуется в 1С, тоже использует очередь сообщений. Когда мы запускаем задание через асинхронную функцию, платформа 1С создает для неё обработчик и либо сразу запускает его, либо после того, как обработает текущее сообщение окна. Мы же получаем эмуляцию многопоточного режима, она работает успешно на оконных, диалоговых и файловых операциях, за счет того, что данные операции способны освобождать ресурсы и передавать управление главному окну в ожидании оконных сообщений. Поэтому асинхронные операции в основном используются в таких операциях, как Предупреждение, Вопрос, Диалог выбора файла, загрузок файлов и т.д.
Что касается конкретно компонент: не думаю, что в большинстве случаев это уместно, но есть длительные операции по загрузке больших изображений, обработке их, работе с торговым и другим оборудованием, которые тоже освобождают свои ресурсы для главного окна программы, и тогда они действительно полезны. В результате того, какой метод "Обратного вызова" или через Обещание используется, мы имеем приоритет начала выполнения операции, которой вызываем асинхронную функцию. В старом варианте она вызывается сразу, а затем управление передается текущему окну, а в новом через Обещание, операция передается после обработки текущего оконного сообщения, как я предполагаю главного окна программы. Отсюда и выходит, что пока мы не выйдем из Модального диалога, новая операция через Ожидание - не начнется...
Резюме:
Чтобы компонента была совместима с асинхронными операциями, и могла бы использоваться в браузерах, которые требуют исключительно асинхронных операций, то она должна иметь статический набор свойств и методов, которые не меняют ни состав, ни порядок свойств, и нумерация методов не должна меняться.
Если компонента не рассчитана на использование браузеров, то асинхронные операции лучше использовать только на действительно длительных операциях, таких как, например, Эквайринг, загрузка и выгрузка фото и видео-контента, и других, связанных с файловым обменом, а также диалоговых окнах, если таковые присутствуют. В обычных случаях, лучше избегать использования асинхронных операций.
В способе "Обратного вызова" - не ленитесь передавать маркеры как минимум названия свойства или метода в объект Оповещение. А также создайте и передавайте процедуру обработки исключений, тогда Вы точно будете знать, на какой операции у Вас оно произошло. Эта процедура может быть одна на текущий модуль или находиться в Общем модуле.
На этом пока все, буду рад, если кому-то это покажется полезным.