Во-вторых, какая связь между многопоточностью и async/await? Асинхронность и многопоточность это разные вещи.
Вам удалось донести до меня ключевую особенность async/await — возможность работы в одном потоке выполнения. Данной возможности в 1С нет, поэтому я признаю что async/await в платформе 1С нет
Где в вики написано про стек? Вы опять начинаете приплетать особенности реализации. Я вообще не вижу смысла что-то вам доказывать. Функциональности платформы 1С достаточно для написания многопоточных приложений с удобным механизмом синхронизации между потоками.
на время ее выполнения вызывающий поток будет занят.
Вот вам пример реализации await, управление сразу вернется в вызываемый поток
Функция await(ВызываемаяФункция, Параметр1 = Неопределено, Параметр2 = Неопределено)
ПараметрыЗадания = Новый Массив;
Если Параметр1 <> Неопределено Тогда
ПараметрыЗадания.Добавить(Параметр1);
КонецЕсли;
Если Параметр1 <> Неопределено Тогда
ПараметрыЗадания.Добавить(Параметр2);
КонецЕсли;
Возврат ФоновыеЗадания.Выполнить(ВызываемаяФункция, ПараметрыЗадания);
КонецФункции
Почему? На клиенте вы делаете обработчик ожидания, который периодически проверяет статус фонового задания и если оно завершилось возвращает результат. Такой подход повсеместно используется в той же 1С:ERP
Non-blocking — это ровно то требование, которое я озвучивал выше, просто другими словами
Нигде в статье не написано, что превращение обычного вызова в асинхронный должно делаться ключевым словом async. Я могу определить глобальную функцию await(ВызываемыяФункция, Параметр1… Параметр2), в ней делать вызов переданной функции через фоновое задание и затем использовать ее с помощью
В текущей реализации C++ нет ключевого слова await, а вместо ключевого слова async используется функция — по вашему там тоже нет поддержки async/await?
Так вы и пишите тогда, что async/await не такой как в C#, а не «Как может не нравиться то, чего просто нет?» Потому что согласно википедии — это возможность задания зависимостей одних задач от других en.wikipedia.org/wiki/Async%2Fawait.
это по прежнему блокирует поток основной, мы всего лишь получаем возможность задачу распараллелить и дождаться завершения.
Я писал выше, что вы можете сделать отдельную процедуру, которая будет на вход получать ФоновоеЗадание — при этом сама инициировать новое фоновое задание, ожидать в нем завершения переданного и при необходимости писать необходимую информацию об ошибке.
Например мы сделали процедуру, которая отправляет почту в отдельном фоновом задании — РаботаСПочтой.ПослатьАсинхронно(Профиль, Сообщение). Теперь вы хотите, чтобы некое другое задание обрабатывала результат этой отправки:
ОбщегоНазначения.ОбработатьРезультатВФоне(РаботаСПочтой.ПослатьАсинхронно(Профиль, Сообщение))
Ну так покажите, как эти данные передаются без знания об этом вызываемого кода
Каких именно данных вам не хватает для обработки ошибок в моем примере?
Потому что, как я уже говорил, это ключевой вопрос
Это для вас ключевой вопрос. Если на платформе 1С возникает потребность асинхронного выполнения — она используется, при необходимости пишутся необходимые библиотеки или обертки. Это достаточно глупо сравнивать предметно-ориентированную платформу с языком общего назначения. Вам написать чего нет в .NET, что есть в платформе 1С?
Я например считаю, что генерики C# гораздо примитивнее шаблонов в C++. Но не кричу на каждом углу, что шаблонов в C# нет.
Ну то есть я должен руками написать всю функциональность.
У нас вопрос не в том, чья библиотека больше подходит под асинхронное выполнение, а о том, что базовая функциональность для этого есть.
И где «емейл не будет послан, если ошибка»?
Вы можете обойти все задания, и если хотя бы в одном статус отличается от Выполнено емейл не отправлять. Разве это не очевидно?
Где асинхрония в отправке емейла?
Вы можете сделать отдельную процедуру для асинхронной отправки и вызывать ее. Все библиотечные функции 1С синхронные, кому нужна асинхронность — пишет сам
то полностью сохраняет контекст вызова, которым можно пользоваться для трассировки.
Объект ФоновоеЗадание вместе с данными во временном хранилище — тот же контекст вызова
Вот был поток (в смысле, thread), в нем вызвали ОжидатьЗавершения — он в этот момент освободится для других задач, или нет
Откуда мне знать, как в закрытой платформе реализовано ожидание. Разумеется цикл не гоняет, вероятнее всего переходит в спящий режим.
Получу ли я в этом случае ошибки скачивания файлов?
Это зависит от того, как вы реализуете обработку ошибок в ЗагрузитьИОтправитьФайлы. Вы можете в том случае, если хотя бы один файл загрузился с ошибкой вызвать исключение со списком ошибочных файлов
Просто покажите код.
Вот кусок который нужно вставить вместо
Сообщение = Новый ИнтернетПочтовоеСообщение;
Сообщение.Получатели.Добавить(Адрес);
Для Каждого ЭлементСписка Из ВыполненныеЗадания Цикл
Если ЭлементСписка.Значение.Состояние = СостояниеФоновогоЗадания.Завершено Тогда
Сообщение.Вложения.Добавить(ПолучитьИзВременногоХранилища(ЭлементСписка.Представление));
Иначе
Сообщение.Тексты.Добавить(ЭлементСписка.Значение.ИнформацияОбОшибке.Описание());
КонецЕсли;
КонецЦикла;
Профиль = Новый ИнтернетПочтовыйПрофиль;
ИнтернетПочта = Новый ИнтернетПочта;
ИнтернетПочта.Подключиться(Профиль);
ИнтернетПочта.Послать(Сообщение);
ИнтернетПочта.Отключиться();
Покажите мне код, который делает то же самое, что и мой.
Мы обсуждает async/await, а не способы сбора информации об ошибке и записи их в лог. Все это тоже можно сделать
Там опять нет ответа на мой вопрос: что происходит с потоком выполнения, пока эта процедура не завершится?
Я вам привел фрагмент описания из встроенно документации, там явно написано — Ожидает завершения всех фоновых заданий из списка. Что тут не понятного, останавливается выполнение и все.
Вы можете реализовать процедуру, которая сама будет отслеживать выполнение фонового задания, замерять время выполнения, формировать дерево ошибок и вызывать ее:
Мне нужно видеть, что письмо отправляется или не отправляется в зависимости от успешности скачивания файлов
Вы в это место попадете, когда все задания на скачивания файлов завершатся (успешно или с ошибкой)
В цикле по заданиям в ЭлементСписка.Значение.Состояние вы получаете статус завершения, а в ПолучитьИзВременногоХранилища(ЭлементСписка.Представление) то что передало подчиненное задание в основное
Автоматическое отслеживание времени выполнения, автоматическая корреляция всех дочерних записей в лог.
Делать замеры придется самостоятельно с помощью вызова ПолучитьУниверсальнуюДатуВМиллисекундах(), так же как и передавать содержимое ошибки из подчиненных фоновых заданий в основное чтобы записывать их как единое целое. Опять же это все можно реализовать при необходимости
Чтобы знать, что и когда происходит в коде.
Вы можете всю трассировочную информацию писать в журнал регистрации
Я повторю вопрос, поскольку вы на него не ответили, а он первый по важности, на самом деле
1С не выкладывает документацию по платформе в общий доступ. Можете зарегистрироваться на its.1c.ru бесплатно на 7 дней. Описание этой процедуры: Ожидает завершения всех фоновых заданий из списка. Если хотя бы одно задание завершено аварийно, ожидание прерывается и выдается ошибка выполнения задания. Если наступил таймаут, выдается ошибка ожидания задания. Ожидать завершения заданий может только администратор или пользователь, запустивший задания на выполнение.
То есть вы ее вызываете если хотите ожидать выполнения. Если ждать не хотите не вызываете, но и тогда никакой информации о результате выполнения задания вы не получите
Функция ЗагрузитьИОтправитьФайлы(Файлы, Адрес, ЗапускЗадания = Ложь) Экспорт
Если НЕ ЗапускЗадания Тогда
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(Файлы);
ПараметрыЗадания.Добавить(Адрес);
ПараметрыЗадания.Добавить(Истина);
Возврат ФоновыеЗадания.Выполнить("РаботаСФайлами.ЗагрузитьИОтправитьФайлы", ПараметрыЗадания);
КонецЕсли;
КлючЗадания = Новый УникальныйИдентификатор;
Задания = Новый СписокЗначений;
Для Каждого ПутьКФайлу Из Файлы Цикл
АдресХранилища = ПоместитьВоВременноеХранилище(Неопределено);
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(ПутьКФайлу);
ПараметрыЗадания.Добавить(АдресХранилища);
Задание = ФоновыеЗадания.Выполнить("РаботаСФайлами.ЗагрузитьФайл", ПараметрыЗадания);
Задания.Добавить(Задание, АдресХранилища);
КонецЦикла;
ВыполненныеЗадания = Новый СписокЗначений;
Пока Задания.Количество() > 0 Цикл
Попытка
ФоновыеЗадания.ОжидатьЗавершения(Задания.ВыгрузитьЗначения(), 15);
Исключение
КонецПопытки;
МаксИнд = Задания.Количество();
Для Инд = 1 По МаксИнд Цикл
Отбор = Новый Структура("УникальныйИдентификатор", Задания[МаксИнд - Инд].Значение.УникальныйИдентификатор);
Задание = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор)[0];
Если Задание.Состояние <> СостояниеФоновогоЗадания.Активно Тогда
ВыполненныеЗадания.Добавить(Задание, Задания[МаксИнд - Инд].Представление);
Задания.Удалить(МаксИнд - Инд);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Для Каждого ЭлементСписка Из ВыполненныеЗадания Цикл
ЗаписьЖурналаРегистрации("ВложениеФайла", , , , "" + ЭлементСписка.Значение.Состояние + ";" + ПолучитьИзВременногоХранилища(ЭлементСписка.Представление));
КонецЦикла;
ЗаписьЖурналаРегистрации("ОтправкаФайлов", , , , Адрес);
КонецФункции
Объясните только, что значит «вызывающий код асинхронно получает результат выполнения»?
Напишите словами что требуется. Не все тут знатоки C# и тем более особенностей передачи файлов в .NET. И что за ограничение на один метод? Вы написали, что на читабельность внимания не обращать
Вам удалось донести до меня ключевую особенность async/await — возможность работы в одном потоке выполнения. Данной возможности в 1С нет, поэтому я признаю что async/await в платформе 1С нет
Я неправильно написал, вот правильный варинат:
Вот вам пример реализации await, управление сразу вернется в вызываемый поток
Нигде в статье не написано, что превращение обычного вызова в асинхронный должно делаться ключевым словом async. Я могу определить глобальную функцию await(ВызываемыяФункция, Параметр1… Параметр2), в ней делать вызов переданной функции через фоновое задание и затем использовать ее с помощью
В текущей реализации C++ нет ключевого слова await, а вместо ключевого слова async используется функция — по вашему там тоже нет поддержки async/await?
Так вы и пишите тогда, что async/await не такой как в C#, а не «Как может не нравиться то, чего просто нет?» Потому что согласно википедии — это возможность задания зависимостей одних задач от других en.wikipedia.org/wiki/Async%2Fawait.
Я писал выше, что вы можете сделать отдельную процедуру, которая будет на вход получать ФоновоеЗадание — при этом сама инициировать новое фоновое задание, ожидать в нем завершения переданного и при необходимости писать необходимую информацию об ошибке.
Например мы сделали процедуру, которая отправляет почту в отдельном фоновом задании — РаботаСПочтой.ПослатьАсинхронно(Профиль, Сообщение). Теперь вы хотите, чтобы некое другое задание обрабатывала результат этой отправки:
ОбщегоНазначения.ОбработатьРезультатВФоне(РаботаСПочтой.ПослатьАсинхронно(Профиль, Сообщение))
Каких именно данных вам не хватает для обработки ошибок в моем примере?
Это для вас ключевой вопрос. Если на платформе 1С возникает потребность асинхронного выполнения — она используется, при необходимости пишутся необходимые библиотеки или обертки. Это достаточно глупо сравнивать предметно-ориентированную платформу с языком общего назначения. Вам написать чего нет в .NET, что есть в платформе 1С?
Я например считаю, что генерики C# гораздо примитивнее шаблонов в C++. Но не кричу на каждом углу, что шаблонов в C# нет.
У нас вопрос не в том, чья библиотека больше подходит под асинхронное выполнение, а о том, что базовая функциональность для этого есть.
Вы можете обойти все задания, и если хотя бы в одном статус отличается от Выполнено емейл не отправлять. Разве это не очевидно?
Вы можете сделать отдельную процедуру для асинхронной отправки и вызывать ее. Все библиотечные функции 1С синхронные, кому нужна асинхронность — пишет сам
Объект ФоновоеЗадание вместе с данными во временном хранилище — тот же контекст вызова
Откуда мне знать, как в закрытой платформе реализовано ожидание. Разумеется цикл не гоняет, вероятнее всего переходит в спящий режим.
Это зависит от того, как вы реализуете обработку ошибок в ЗагрузитьИОтправитьФайлы. Вы можете в том случае, если хотя бы один файл загрузился с ошибкой вызвать исключение со списком ошибочных файлов
Вот кусок который нужно вставить вместо
Мы обсуждает async/await, а не способы сбора информации об ошибке и записи их в лог. Все это тоже можно сделать
Я вам привел фрагмент описания из встроенно документации, там явно написано — Ожидает завершения всех фоновых заданий из списка. Что тут не понятного, останавливается выполнение и все.
Вы можете реализовать процедуру, которая сама будет отслеживать выполнение фонового задания, замерять время выполнения, формировать дерево ошибок и вызывать ее:
Если у вас есть базовый механизм ожидания выполнения группы заданий и возможность передачи информации между ними вы можете реализовать любую логику.
Вы можете сделать вызов:
и выполнение остановится до завершения этого вызова.
Можете просто сделать вызов:
и выполнение программы продолжится
Вы в это место попадете, когда все задания на скачивания файлов завершатся (успешно или с ошибкой)
В цикле по заданиям в ЭлементСписка.Значение.Состояние вы получаете статус завершения, а в ПолучитьИзВременногоХранилища(ЭлементСписка.Представление) то что передало подчиненное задание в основное
Делать замеры придется самостоятельно с помощью вызова ПолучитьУниверсальнуюДатуВМиллисекундах(), так же как и передавать содержимое ошибки из подчиненных фоновых заданий в основное чтобы записывать их как единое целое. Опять же это все можно реализовать при необходимости
Вы можете всю трассировочную информацию писать в журнал регистрации
1С не выкладывает документацию по платформе в общий доступ. Можете зарегистрироваться на its.1c.ru бесплатно на 7 дней. Описание этой процедуры:
Ожидает завершения всех фоновых заданий из списка. Если хотя бы одно задание завершено аварийно, ожидание прерывается и выдается ошибка выполнения задания. Если наступил таймаут, выдается ошибка ожидания задания. Ожидать завершения заданий может только администратор или пользователь, запустивший задания на выполнение.
То есть вы ее вызываете если хотите ожидать выполнения. Если ждать не хотите не вызываете, но и тогда никакой информации о результате выполнения задания вы не получите
Она вернет объект ФоновоеЗадание, у которого при необходимости можно вызвать метод ОжидатьЗавершения()
Их можно получить из в цикле ВыполненныеЗадания через поле ИнформацияОбОшибке, там будет и описание и строка модуля
Вам реально нужен пример работы с объектом ИнтернетПочта? Я пишу событие в журнал регистрации ОтправкаФайлов когда я готов отправить письмо
Что вы имеете ввиду? Для чего он вам?
Не умеете. Первый в поиске гугла по строке «ФоновыеЗадания.ОжидатьЗавершения „forum.mista.ru/topic.php?id=699578
Объясните только, что значит «вызывающий код асинхронно получает результат выполнения»?