Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
9 / 9 / 0
Регистрация: 27.01.2013
Сообщений: 248
1

Асинхронное программирование await async

23.03.2015, 21:34. Показов 2498. Ответов 9
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет!

Пытаюсь разобраться с асинхронным вызовом методов. Узнал такую вещь: если предполагается, что некоторый метод может долго выполнятся, то его можно перенести в "фоновое" выполнение, а управление отдать в вызывающий метод. Решил разобраться с этим и написал для начала обычный код без асинхронного программирования.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Test
{
    public  static void Download()
    {        
        WebClient wc = new WebClient();
        byte[] data = wc.DownloadData(@"http://www.ukraine.com.ua/static/100MB.bin");
        Console.WriteLine("Welcome to");
        Console.WriteLine("Hell");
        Console.WriteLine(data.Length);
    }
 
    static void Main()
    {
        Download();
    }
}
Здесь вроде все понятно, пока загружается 100мб файл, соответственно остальные инструкции в методе Download() не выполняются до окончания загрузки. То есть идет последовательное выполнение. Далее я решил поэкспериментировать с await и async и написал следующий код:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Test
{
    public async  static void Download()
    {        
        WebClient wc = new WebClient();
        byte[] data = await wc.DownloadDataTaskAsync(@"http://www.ukraine.com.ua/static/100MB.bin");        
        Console.WriteLine("Welcome to");
        Console.WriteLine("Hell");
        Console.WriteLine(data.Length);
    }
 
    static void Main()
    {
        Download();
    }
}
Как видно, логика кода такая же, только добавлены await и async и под них изменен метод на DownloadDataTaskAsync.

В этом коде я ожидал такое поведение:

1. Файл начинает скачиваться.
2. Так как закачка переходит в фоновый режим, то управление возвращается методу Download(), и следовательно выводится на консоль Welcome to Hell.
3. По окончании загрузки файла выводится результат Length.
Однако всего этого не происходит, а вместо этого просто запускается консоль без единого сообщения, кроме того, чтобы я нажал эникей. Почему так происходит, или где я ошибся в коде?

Спасибо.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.03.2015, 21:34
Ответы с готовыми решениями:

Async, await
Объясните работу async, await. Облазил весь интернет, но ничего толкового не нашел. Заранее...

Использование async/await
пытался написать такой тестовый код: нифига не работает, я видимо что-то неправильно делаю. Что...

Непонятная работа async await
Здравствуйте. В общем, все есть на скриншоте. Вопрос: что за фигня?

Пауза через async/await
Написал процедуру Пауза на C# с помощью async/await, но почему-то не работает. Вот код: private ...

9
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
23.03.2015, 21:58 2
bazyzy, Ну вы же сами примяете оператор await. А этот оператор останаваливает поток до получения резульатата из Task, который возвращается из метода DownloadDataTaskAsync.
Если вы хотите что бы работало так как вы ожидаете, код должен быть таким:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Test
{
    public async  static void Download()
    {        
        WebClient wc = new WebClient();
        var task = wc.DownloadDataTaskAsync(@"http://www.ukraine.com.ua/static/100MB.bin");        
        Console.WriteLine("Welcome to");
        Console.WriteLine("Hell");
        byte[] data = await task;
        Console.WriteLine(data.Length);
    }
 
    static void Main()
    {
        Download();
    }
}
1
9 / 9 / 0
Регистрация: 27.01.2013
Сообщений: 248
24.03.2015, 02:42  [ТС] 3
Но если я правильно понимаю, то он приостанавливает поток ради метода DownloadDataTaskAsync, а когда этот метод вернет результат, тогда поток возобновляется. Но у меня же выходит, что как только доходит дело до строки где вызывается этот метод, то программа дальше даже и не идет по строкам кода, а завершается как выполненная. Вы дали код, но он тоже не работает ожидаемо, он просто выводит Welcome to Hell и программа завершается без загрузки файла и вызова Lenght для массива
0
Warrior
500 / 427 / 177
Регистрация: 23.11.2014
Сообщений: 932
24.03.2015, 03:38 4
https://msdn.microsoft.com/ru-... 56528.aspx
Оператор await применяется к задаче в асинхронных методах, для того, чтобы приостановить выполнение метода до тех пор, пока ожидаемая задача не завершится
1
Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
24.03.2015, 08:16 5
bazyzy,
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
using System;
using System.Threading;
using System.Threading.Tasks;
 
namespace ConsApp_Download
{
    class Program
    {
        public async static void Download()
        {
            int result = await DoWorkAsync();
 
            Console.WriteLine("Welcome to");
            Console.WriteLine("Hell");
            Console.WriteLine(result);
        }
 
        static void Main(string[] args)
        {
            Download();
            Console.ReadKey();
        }
 
        private static Task<int> DoWorkAsync()
        {
            return Task<int>.Factory.StartNew(() =>
            {
                Thread.Sleep(2000);
                return 20;
            });
        }
    }
}
1
Эксперт .NETАвтор FAQ
10410 / 5140 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
24.03.2015, 09:55 6
Лучший ответ Сообщение было отмечено bazyzy как решение

Решение

Цитата Сообщение от bazyzy Посмотреть сообщение
не идет по строкам кода, а завершается как выполненная
А это потому, что ваш метод Download объявлен как async.
Когда внутри метода async вы вызываете await, управление передеается во внешний метод (т.е. в Main). А поскольку в Main у вас больше кода нет, то программа завершается.

Вот так все работает:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    class Program
    {
        public async static void Download()
        {        
            WebClient wc = new WebClient();
            var task = wc.DownloadDataTaskAsync(@"http://www.ukraine.com.ua/static/100MB.bin");        
            Console.WriteLine("Welcome to");
            Console.WriteLine("Hell");
            byte[] data = await task;
            Console.WriteLine(data.Length);
        }
 
        static void Main()
        {
            Download();
            
            while(true)
                Thread.Sleep(1000);//ждем
        }
    }
Возможен также другой вариант:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    class Program
    {
        public static void Download()
        {        
            WebClient wc = new WebClient();
            var task = wc.DownloadDataTaskAsync(@"http://www.ukraine.com.ua/static/100MB.bin");        
            Console.WriteLine("Welcome to");
            Console.WriteLine("Hell");
            task.Wait();
            Console.WriteLine(task.Result.Length);
        }
 
        static void Main()
        {
            Download();
        }
    }
Здесь вместо await используется Task.Wait() и теперь метод Download() становится синхронным, без async.
1
9 / 9 / 0
Регистрация: 27.01.2013
Сообщений: 248
24.03.2015, 12:23  [ТС] 7
Цитата Сообщение от Storm23 Посмотреть сообщение
Когда внутри метода async вы вызываете await, управление передается во внешний метод (т.е. в Main).
Аааа, вот оно что. Это проясняет ситуацию. Я думал, что этот внешний метод - DownloadDataTaskAsync, а не маин. И следовательно я предполагал, что когда DownloadDataTaskAsync выполнится, то код продолжит свое выполнение.
0
Эксперт .NET
4432 / 2092 / 404
Регистрация: 27.03.2010
Сообщений: 5,657
Записей в блоге: 1
24.03.2015, 12:51 8
Можешь ещё так ждать, но смысла в этом ноль, как мне кажется:
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
    class Program
    {
        public async static void Download()
        {
            Task<int> task = DoWorkAsync();
            Task.WaitAll(task);
 
            Console.WriteLine("Welcome to");
            Console.WriteLine("Hell");
            Console.WriteLine(task.Result);
        }
 
        static void Main(string[] args)
        {
            Download();
            Console.ReadKey();
        }
 
        private static Task<int> DoWorkAsync()
        {
            return Task<int>.Factory.StartNew(() =>
            {
                Thread.Sleep(2000);
                return 20;
            });
        }
    }
Добавлено через 46 секунд
bazyzy, вот посмотри и не заморачивайся подобными вопросами
1
9 / 9 / 0
Регистрация: 27.01.2013
Сообщений: 248
24.03.2015, 13:14  [ТС] 9
О, спасибо огромное за информацию и видеоурок !! Меня сбила с толку книга по ASP.NET MVC. Сейчас скриншот приложу
0
Master of Orion
Эксперт .NET
6098 / 4954 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
24.03.2015, 13:43 10
bazyzy, там всё правильно написано, просто вы не так поняли...
1
24.03.2015, 13:43
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.03.2015, 13:43
Помогаю со студенческими работами здесь

Понимание потоков и async await
Всем привет, хочу задать пару вопросов опытным программистам: 1)Что такое потоки ? как они...

Async/await различия методов
В чем разница между AsyncWork1/2/3 private async void btnStart_Click_1(object sender, EventArgs...

Sockets client+server with await/async c# 5.0
Уже долго пытаюсь найти хотя бы какой то пример, но пока безуспешно, поэтому обращаюсь с просьбой к...

async/await как замена многопоточности
Можно ли использовать эту конструкцию как полную замену потокам, или в каких случаях не получится?


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru