|
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
|
|
Почему сделано так, что нельзя ожидать async void методы?22.04.2021, 16:58. Показов 6915. Ответов 18
Метки async await (Все метки)
Привет!
Чем внутри отличается async void от async Task? Как я понимаю, особо ничем. Для обоих случаев генерируется, если не одинаковый, то очень похожий код. Разница в том, что в случае с void возникшее исключение пробрасывается в поток из пула потоков, а в случае с Task исключение устанавливается внутрь задачи. Или там ещё что-то? Причем и там и там, если в нашем коде есть await, под капотом создается задача, и работает оно в обоих случаях очень похоже, отличается только способ обработки возникшего исключения. И возникает пара вопросов: 1. Почему не сделали возможность в языке писать await MyVoidMethod()? 2. Пробрасывание исключение в пул потоков, как я понимаю, это следствие невозможности из языка выполнить await. Если это так, то зачем исключение пробрасывать: что бы оно случайно не осталось незамеченным или какие-то есть другие причины этого?
0
|
|
| 22.04.2021, 16:58 | |
|
Ответы с готовыми решениями:
18
Почему нельзя несколько раз ожидать ValueTask Почему в async void методе не перехватывается исключение? Дописать методы void pop_back(void); T& back(void); T& front(void); void erase (iterator p) |
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
||||
| 22.04.2021, 17:16 | ||||
|
Что он должен ожидать, если void ничего не возвращает?
0
|
||||
|
1152 / 860 / 263
Регистрация: 30.04.2009
Сообщений: 3,603
|
||
| 22.04.2021, 20:10 | ||
|
0
|
||
|
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
|
||||
| 23.04.2021, 08:25 [ТС] | ||||
|
0
|
||||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||||||||||||||||
| 23.04.2021, 12:33 | |||||||||||||||||
|
Оператор await — это не более, чем разукрашенный return.В момент вызова await работа метода завершается и управление возвращается в точку вызова. В C# нет существует асинхронных вызовов. Вызов любого метода всегда синхронный. В этом легко убедиться:
Вам даже компилятор услужливо выдаст предупреждение, что метод MyVoidMethod всегда выполняется синхронно. В языке существует понятие асинхронное ожидаение — это когда выполнение части работы откладывается до тех пор, пока выполняющаяся другая работа не закончится. Когда компилятор встречает в коде await, он разворачивает это примерно в это:
Допустим, реализация вашего MyVoidMethod выглядит так:
Теперь замените тип возвращаемого значения MyVoidMethod с Task на void. В последней строчке уже ничего нельзя вернуть, т.к. метод void — будет просто завершение работы метода без возврата объекта, представляющего продолжение выполнения остальной части метода — с чем компилятору работать в точке вызова?
1
|
|||||||||||||||||
|
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
|
||||||||||||||||||||||
| 23.04.2021, 14:04 [ТС] | ||||||||||||||||||||||
|
kolorotur, спасибо за развернутый ответ! Но я все равно не понимаю следующего.
void IAsyncStateMachine.MoveNext(), который в обоих случаях void. И как я понимаю, оно развернется в обоих случаях в код вида:
0
|
||||||||||||||||||||||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
||
| 23.04.2021, 16:49 | ||
|
Но если асинхронный метод void, то в точку вызова нечего возвращать и не на чем строить машину состояний для проверки полного завершения работы метода.
0
|
||
|
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
|
||
| 24.04.2021, 12:38 [ТС] | ||
|
0
|
||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||||||
| 24.04.2021, 16:51 | |||||||
|
Чтобы вызвать MoveNext, должен быть экземпляр, на котором его вызывать. Этот экземпляр возвращает асинхронный метод в точку вызова. Если асинхронный метод — void, то он ничего не возвращает и не на чем вызывать MoveNext, следовательно не во что преобразовывать await, как результат — await нельзя использовать с void-методами. Добавлено через 1 минуту Это примерно как пытаться использовать foreach на void-возвращающем методе:
1
|
|||||||
|
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
|
||||||
| 26.04.2021, 08:45 [ТС] | ||||||
|
kolorotur, я теперь, кажется, понял о чем вы выше говорили. Но я теперь не понимаю следующего. AsyncVoidMethodBuilder на самом деле содержит у себя внутри какую-то задачу:
0
|
||||||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
||||
| 26.04.2021, 10:28 | ||||
|
Снаружи этого метода (в точке вызова) строить нечего, т.к. void метод не возвращает никакой информации о проделываемой работе — на то он и void. В других ситуациях его использование не имеет смысла. Асинхронное ожидание конвертируется в конечный автомат, используя возвращаемое значение асинхронного метода. Если метод ничего не возвращает, то конечный автомат строить не из чего. А поскольку async void создан только для обратной совместимости, постольку разработчики не стали тратить впустую время на попытки реализовать какой-то другой механизм ожидания async void методов за ненадобностью: легаси-код нигде не использует await при запуске событий, а новый код может для асинхронных событий использовать делегат, возвращающий Task или любой другой awaitable.
1
|
||||
|
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
|
|
| 26.04.2021, 16:07 [ТС] | |
|
kolorotur, это не точно, но кажется, начинает потихоньку доходить. Спасибо за ответ!
0
|
|
|
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
|
|
| 27.04.2021, 08:29 [ТС] | |
|
kolorotur, с методом void я вроде понял, но все равно интересно, почему бы было не сделать, что бы async void методы превращались компилятором в async Task? Существующий AsyncVoidMethodBuilder это вроде позволяет (в смысле вернуть задачу из него, сделав её публичной). Надо было бы ещё всего лишь поменять тип метода с void на Task. От этого ничего бы не сломалось вроде: для тех, кто вызывал бы метод без ожидания - было бы поведение аналогичное текущему. Но для тех кому надо было бы дождаться - появилась бы такая возможность.
0
|
|
|
1524 / 914 / 329
Регистрация: 17.05.2015
Сообщений: 3,438
|
||
| 27.04.2021, 09:13 | ||
|
0
|
||
|
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
|
|
| 27.04.2021, 10:18 [ТС] | |
|
2
|
|
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||||||||
| 27.04.2021, 10:27 | |||||||||
Единственная ответственность конструктора — инициализация памяти, занимаемой объектом. Что, например, будет твориться, если список таких объектов будет десериализирован? Добавлено через 8 минут Полагаю, что создатели языка не посчитали "заглушку", созданную исключительно для обратной совместимости, достаточно важным функционалом чтобы тратить на нее больше необходимого минимума. Но это, конечно, всего лишь мои предположения. Если интересен ответ именно разработчиков — поинтересуйтесь у них сами.
2
|
|||||||||
|
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
|
||
| 29.04.2021, 10:52 [ТС] | ||
|
И мне интересно для себя понять: да, это действительно по трудозатратам ерунда, но решили, что условно даже пол дня тратить на это не целесообразно; либо же на самом деле это совсем не ерунда в техническом плане и все не так просто, как я себе представляю?
0
|
||
|
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
|
|||
| 29.04.2021, 11:29 | |||
|
Что делать, если этот метод — реализация интерфейса? Или переопределенный метод базового типа? Как быть с делегатами на этот метод? Внешний же код ничего не знает о том, async этот метод или не async — это деталь реализации метода. Внезапно какой-то void-метод из сторонней сборки нельзя присвоить делегату Action, потому что под капотом он, оказывается, вовсе не void. Выведение типов в лямбда-выражениях — это будет вообще отдельная песня. Сейчас на дворе уже 9-я версия, наверняка можно накинуть еще 100-200 страниц на весь новый функционал. В таких сложных языках почти не бывает копеечных решений — практически любое изменение устроит цепную реакцию, затрагивающую другие правила языка.
1
|
|||
|
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
|
|
| 29.04.2021, 13:08 [ТС] | |
|
kolorotur, теперь стало понятнее. Спасибо за ответ!
1
|
|
| 29.04.2021, 13:08 | |
|
Помогаю со студенческими работами здесь
19
Что не так сделано ? Почему в С++ это сделано именно так? Объяснение для НЕ программиста Почему нельзя override private методы? Что не так сделано с плеером JW Player Калькулятор. Подскажите что сделано не так? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Уведомление о неверно выбранном значении справочника
Maks 06.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "НарядПутевка", разработанного в конфигурации КА2.
Задача: уведомлять пользователя, если в документе выбран неверный склад. . .
|
Установка Qt Creator для C и C++: ставим среду, CMake и MinGW без фреймворка Qt
8Observer8 05.04.2026
Среду разработки Qt Creator можно установить без фреймворка Qt. Есть отдельный репозиторий для этой среды: https:/ / github. com/ qt-creator/ qt-creator, где можно скачать установщик, на вкладке Releases:. . .
|
AkelPad-скрипты, структуры, и немного лирики..
testuser2 05.04.2026
Такая программа, как AkelPad существует уже давно, и также давно существуют скрипты под нее. Тем не менее, прога живет, периодически что-то не спеша дополняется, улучшается. Что меня в первую очередь. . .
|
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2.
Данный документ берёт данные из другого нетипового документа. . .
|
|
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
|
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2.
Задача: реализовать программный контроль на предмет проведения документа. . .
|
Программный контроль заполнения реквизитов табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2.
Задача:
1. Реализовать контроль заполнения реквизита. . .
|
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение:
DISM / Online / Add-Capability / CapabilityName:WMIC~~~~
Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
|