Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
Заблокирован

Метод async без await в примере книги

06.11.2023, 22:50. Показов 1463. Ответов 10

Студворк — интернет-сервис помощи студентам
В книге Стивена Клири "Конкурентность в c#" на стр 48 (в переводе) в коде примера используются методы async без await, вот такие
C#
1
2
3
4
async Task ThrowNotImplementedExceptionAsync()
{
throw new NotImplementedException();
}
Что бы это значило?
Попалось обсуждение на английском
https://stackoverflow.com/ques... acks-await
Но я там так и не понял к чему в итоге люди пришли. Слишком много слов)
Главное, что не понятно - зачем в книге такое писать? Причем, там в книге никаких пояснений по ходу не было.
(у меня складывается мнение, что текст в переводе у этой книги вообще неудачный)
На всякий случай весь код примера из книги
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
async Task ThrowNotImplementedExceptionAsync()
{
throw new NotImplementedException();
}
async Task ThrowInvalidOperationExceptionAsync()
{
throw new InvalidOperationException();
}
async Task ObserveOneExceptionAsync()
{
var task1 = ThrowNotImplementedExceptionAsync();
var task2 = ThrowInvalidOperationExceptionAsync();
try
{
await Task.WhenAll(task1, task2);
}
catch (Exception ex)
{
// "ex" - либо NotImplementedException, либо InvalidOperationException.
...
}
}
async Task ObserveAllExceptionsAsync()
{
var task1 = ThrowNotImplementedExceptionAsync();
var task2 = ThrowInvalidOperationExceptionAsync();
Task allTasks = Task.WhenAll(task1, task2);
try
{
await allTasks;
}
catch
{
AggregateException allExceptions = allTasks.Exception;
...
}
}
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
06.11.2023, 22:50
Ответы с готовыми решениями:

Переписать асинхронный метод без использования async/await
Ломаю голову как переписать асинхронный метод что бы достичь того же эффекта как при использовании async/await. К примеру(пример взят из...

Async/ await как правильно ввести данные в async метод (консоль)
Привет , кто то может помочь ?) проблема в тому что у меня есть async метод который запускается из Main, по среди этого метода...

Асинхронный метод: async + await
Доброго времени суток! Есть достаточно простой метод: public UserControl1 ListToArray() { UserControl1 uc =...

10
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
06.11.2023, 23:28
Лучший ответ Сообщение было отмечено titan4ik как решение

Решение

Цитата Сообщение от titan4ik Посмотреть сообщение
Что бы это значило?
Что исключение не вылетит до тех пор, пока не произведется доступ к определенным членам возвращаемой из метода таски либо вручную, либо через await.
Если убрать async, то исключение вылетит при вызове метода, не дожидаясь возврата таски.

Цитата Сообщение от titan4ik Посмотреть сообщение
Главное, что не понятно - зачем в книге такое писать?
Приведенный пример демонстрирует как получать информацию обо всех возможных исключениях при ожидании множества тасков с помощью метода WhenAll, потому в данном примере нужно чтобы исключение вылетало при await WhenAll, а не при вызове методов, возвращающих таски для последующего ожидания в WhenAll.
Т.е. суть примера — демонстрация обработки исключений, а все остальное — карниз и строительные леса для этой демонстрации.
1
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
06.11.2023, 23:32
очень похоже что данные методы -- просто пример, когда таска падает с какой-либо ошибкой. Почему выбрали именно NotImplementedException и InvalidOperationException -- скорее всего чтобы продемонстрировать как разные исключения потом агрегируются в catch (Exception ex)

Теперь почему мы пишем async без await. Дело в том что нам нужно создать таску, т.е. метод всегда должен вернуть объект Task. Но сама задача должна упасть с ошибкой, поэтому в теле задачи просто вызов исключения. А так как ожидания для этого никакого не требуется, то await и отсутствует. По идеи это эквивалент такому

C#
1
Task GetTaskWithException() => Task.Run(() => throw new Exception());
Вот чтобы не строчить Task.Run, которому ещё нужно передать делегат, можно просто написать async метод.
1
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,115
Записей в блоге: 2
06.11.2023, 23:48
Цитата Сообщение от Wolfdp Посмотреть сообщение
По идеи это эквивалент такому
Нет.
Например, проверьте стек вызовов при исключениях. Есть и другие отличия.
1
Эксперт .NET
 Аватар для Wolfdp
3790 / 1767 / 371
Регистрация: 15.06.2012
Сообщений: 6,543
Записей в блоге: 3
07.11.2023, 01:12
Элд Хасп, я немного не про то. Оба подхода подразумевает что вызов метода отработает без ошибки и вернет Task. Сам по себе объект Task не "провоцирует" появление исключения, это вполне себе валидный объект. В вот уже ожидания этого Task вызовет исключение. Грубо говоря я про этот момент

C#
1
2
3
4
5
6
7
8
9
10
11
12
async Task ThrowExceptionAsync() => throw new Exception();
 
var task = ThrowExceptionAsync(); // ошибки нет, нам просто возращается задача
 
try
{
    await task;
}
catch (Exception ex)
{
    ;
}
А вот такая запись уже завалится

C#
1
2
3
4
5
6
7
8
9
10
11
12
Task ThrowExceptionAsync() => throw new Exception();
 
var task = ThrowExceptionAsync(); // тут ошибка
 
try
{
    await task;
}
catch (Exception ex)
{
    ;
}
Ну а если действительно приводить условную полную аналогию, то "да": правильнее кажись так

C#
1
2
3
4
5
6
7
8
9
10
11
12
Task ThrowExceptionAsync() => Task.Run(async () => throw new Exception());
 
var task = ThrowExceptionAsync();
 
try
{
    await task;
}
catch (Exception ex)
{
    ;
}
2
Заблокирован
07.11.2023, 14:45  [ТС]
С целью полноты информации и объективности для.
Каюсь, я там как-то просмотрел (?!) объяснение (после кода). Но во-первых его лучше бы до кода дать, как прелюдию. А во-вторых, отдельно нужно было бы подтвердить что и так можно - async без await - если очень нужно. Ибо изначально всегда читал, что не надо так делать - по понятным причинам.
Вот цитата из книги.
Обратите внимание: в предыдущем примере методы ThrowNotImplementedExceptionAsync и ThrowInvalidOperationExceptionAsync не выдают свои исключения напрямую; они используют ключевое слово async, поэтому исключения перехватываются и помещаются в задачу, которая возвращается нормальным образом. Это нормальное поведение методов, которые возвращают типы, допускающие ожидание.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,115
Записей в блоге: 2
07.11.2023, 19:11
Цитата Сообщение от Wolfdp Посмотреть сообщение
Ну а если действительно приводить условную полную аналогию, то "да": правильнее кажись так
Нет.
1) Приведённый в топе пример - синхронный. Несмотря на то, что возвращает Task.
А Task.Run(async () => throw new Exception()); асинхронный.

2) В исходном методе исключение будет выкинуто сразу в методе ThrowExceptionAsync.
В с Task.Run в лямбда методе, оттуда попадёт в таск созданным руном, из него будет отловлен авайтом, будет создано новое исключение для ThrowExceptionAsync. В котором исходное будет записано в InnerException.
0
07.11.2023, 19:52

Не по теме:

Элд Хасп, хм... насчет InnerException -- вроде не так работает. Ниже пример, как проверял. Но в целом кажись понял про что вы: в случае Task.Run мы всегда из пула дергаем тред и помещаем выполнение кода туда. С async этого естественно не происходит. Хотя стектрейсы у них подозрительно похожи.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//async Task ThrowExceptionAsync()
//{
//    CheckThread("task");
//    throw new CustomException();
//}
 
Task ThrowExceptionAsync() => Task.Run(async () =>
{
    CheckThread("task");
    throw new CustomException();
});
 
void CheckThread(string val) 
    => Console.WriteLine($"{val} - {Thread.CurrentThread.ManagedThreadId}");
 
CheckThread("main");
var task = ThrowExceptionAsync();
try
{
    await task;
}
catch (CustomException ex)
{
    CheckThread("catch");
    var stackTrace = ex.StackTrace;
    ;
}
 
class CustomException : Exception { }

0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,115
Записей в блоге: 2
07.11.2023, 23:12
Цитата Сообщение от Wolfdp Посмотреть сообщение
Хотя стектрейсы у них подозрительно похожи.
Проверьте:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
    public static class TestAsyncException
    {
        private static async Task ThrowExceptionAsync()
        {
            CheckThread("Async");
            throw new CustomException();
        }
        private static void CheckThread(string val)
            => Console.WriteLine($"{val} - {Thread.CurrentThread.ManagedThreadId}");
 
        private static Task ThrowExceptionRun() => Task.Run(() =>
        {
            CheckThread("Run");
            throw new CustomException();
        });
 
        public static async Task Start()
        {
            CheckThread("main");
            var task = ThrowExceptionAsync();
            try
            {
                await task;
            }
            catch (CustomException ex)
            {
                CheckThread("\r\n*****************************\r\ncatch");
                var stackTrace = ex.StackTrace;
                CheckThread(stackTrace);
            }
 
            task = ThrowExceptionRun();
            try
            {
                await task;
            }
            catch (CustomException ex)
            {
                CheckThread("\r\n*****************************\r\ncatch");
                var stackTrace = ex.StackTrace;
                CheckThread(stackTrace);
            }
        }
    }
C#
1
   await TestAsyncException.Start();
Вывод:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
main - 1
Async - 1
 
*****************************
catch - 1
   at Core2023.TestAsyncException.ThrowExceptionAsync() in D:\Users\EldHa\Мои проекты\CyberForurm\CyberForumConsole\Core2023\TupleHelper.cs:line 120
   at Core2023.TestAsyncException.Start() in D:\Users\EldHa\Мои проекты\CyberForurm\CyberForumConsole\Core2023\TupleHelper.cs:line 137 - 1
Run - 4
 
*****************************
catch - 4
   at Core2023.TestAsyncException.<>c.<ThrowExceptionRun>b__2_0() in D:\Users\EldHa\Мои проекты\CyberForurm\CyberForumConsole\Core2023\TupleHelper.cs:line 128
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
   at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
   at Core2023.TestAsyncException.Start() in D:\Users\EldHa\Мои проекты\CyberForurm\CyberForumConsole\Core2023\TupleHelper.cs:line 149 - 4
0
08.11.2023, 01:02

Не по теме:

Цитата Сообщение от Элд Хасп Посмотреть сообщение
Task.Run(() =>
Так действительно стектрейс будет совершенно разный. Но я же запускаю таску с передачей делегата async () =>. В этом случае получаем "пожожие" записи

Code
1
2
3
   at Program.<>c.<<<Main>$>b__0_2>d.MoveNext() in D:\Temp\code\Draft\Draft\Program.cs:line 10
--- End of stack trace from previous location ---
   at Program.<Main>$(String[] args) in D:\Temp\code\Draft\Draft\Program.cs:line 20
Code
1
2
   at Program.<<Main>$>g__ThrowExceptionAsync|0_0() in D:\Temp\code\Draft\Draft\Program.cs:line 4
   at Program.<Main>$(String[] args) in D:\Temp\code\Draft\Draft\Program.cs:line 20
Это изначально и навело на мысль, что подходы вот вообще альтернативны. Конечно, это не так. Собственно запись --- End of stack trace from previous location --- это не бессмысленный комментарий, а жирный индикатор.

0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,115
Записей в блоге: 2
08.11.2023, 08:04
Цитата Сообщение от Wolfdp Посмотреть сообщение
Но я же запускаю таску с передачей делегата async () =>

Моя небрежность.

Да, так разница уменьшится, но всё равно останется, как вы уже заметили.
И самое важное, изменится поток в котором исполняется тело метода, что особенно важно для приложений с чувствительностью к потокам с контекстом синхронизации: Формы, WPF, UWP и др.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.11.2023, 08:04
Помогаю со студенческими работами здесь

Как выполняется метод, использующий async и await?
НаMSDN есть такой пример: async Task&lt;int&gt; AccessTheWebAsync() { HttpClient client = new HttpClient(); Task&lt;string&gt;...

async/await не выполняется метод в асинхронном режиме
Всем доброго времени суток. Ребята, объясните в чем проблема. Приложение в цикле запускает асинхронный метод, который просто возвращает 0,...

Async/await. Как сделать метод асинхронным?
Есть метод, который получает html private static string GetHtml(string id) { using (var client = new...

Асинхронный await метод в цикле в async методе
Почему цикл работает не по порядку, а вразнобой подставляет цифры для int i и в итоге не все цифры подставляет, а значит не достигает...

Выполнение метода в отдельном потоке без await/async
В десктопном WPF проекте с .Net 4.0 необходимо сделать так: private void updateNowButton_Click(object sender, RoutedEventArgs e) ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных через динамический список в справочнике
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Функция заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
10 пpимет, которые всегда сбываются
Maks 31.03.2026
1. Чтобы, наконец, пришла маршрутка, надо закурить. Если сигарета последняя, маршрутка придет еще до второй затяжки даже вопреки расписанию. 2. Нaдоели зима и снег? Не надо переезжать. Достаточно. . .
Перемещение выделенных строк ТЧ из одного документа в другой
Maks 31.03.2026
Реализация из решения ниже выполнена на примере нетипового документа "ВыдачаОборудованияНаСпецтехнику" с единственной табличной частью "ОборудованиеИКомплектующие" разработанного в конфигурации КА2. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru