С наступающим Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
bazyzy
9 / 9 / 0
Регистрация: 27.01.2013
Сообщений: 248
1

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

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

Всем привет!

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

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)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.03.2015, 21:34
Ответы с готовыми решениями:

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

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

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

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

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

9
Storm23
Эксперт .NETАвтор FAQ
6575 / 3987 / 1449
Регистрация: 11.01.2015
Сообщений: 5,164
Записей в блоге: 32
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
bazyzy
9 / 9 / 0
Регистрация: 27.01.2013
Сообщений: 248
24.03.2015, 02:42  [ТС] 3
Но если я правильно понимаю, то он приостанавливает поток ради метода DownloadDataTaskAsync, а когда этот метод вернет результат, тогда поток возобновляется. Но у меня же выходит, что как только доходит дело до строки где вызывается этот метод, то программа дальше даже и не идет по строкам кода, а завершается как выполненная. Вы дали код, но он тоже не работает ожидаемо, он просто выводит Welcome to Hell и программа завершается без загрузки файла и вызова Lenght для массива
0
_exp10der_
Warrior
490 / 417 / 177
Регистрация: 23.11.2014
Сообщений: 932
24.03.2015, 03:38 4
https://msdn.microsoft.com/ru-ru/library/hh156528.aspx
Оператор await применяется к задаче в асинхронных методах, для того, чтобы приостановить выполнение метода до тех пор, пока ожидаемая задача не завершится
1
Casper-SC
Эксперт .NET
3638 / 1843 / 360
Регистрация: 27.03.2010
Сообщений: 5,169
Записей в блоге: 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
Storm23
Эксперт .NETАвтор FAQ
6575 / 3987 / 1449
Регистрация: 11.01.2015
Сообщений: 5,164
Записей в блоге: 32
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
bazyzy
9 / 9 / 0
Регистрация: 27.01.2013
Сообщений: 248
24.03.2015, 12:23  [ТС] 7
Цитата Сообщение от Storm23 Посмотреть сообщение
Когда внутри метода async вы вызываете await, управление передается во внешний метод (т.е. в Main).
Аааа, вот оно что. Это проясняет ситуацию. Я думал, что этот внешний метод - DownloadDataTaskAsync, а не маин. И следовательно я предполагал, что когда DownloadDataTaskAsync выполнится, то код продолжит свое выполнение.
0
Casper-SC
Эксперт .NET
3638 / 1843 / 360
Регистрация: 27.03.2010
Сообщений: 5,169
Записей в блоге: 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
bazyzy
9 / 9 / 0
Регистрация: 27.01.2013
Сообщений: 248
24.03.2015, 13:14  [ТС] 9
О, спасибо огромное за информацию и видеоурок !! Меня сбила с толку книга по ASP.NET MVC. Сейчас скриншот приложу http://i.imgur.com/WRPrkwK.jpg
0
Psilon
Master of Orion
Эксперт .NET
6013 / 4866 / 902
Регистрация: 10.07.2011
Сообщений: 14,477
Записей в блоге: 5
Завершенные тесты: 4
24.03.2015, 13:43 10
bazyzy, там всё правильно написано, просто вы не так поняли...
1
24.03.2015, 13:43
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
24.03.2015, 13:43

Async/await или разница между 2 методами
Добрых времени суток. Есть асинхронный метод: public Task&lt;List&lt;Address&gt;&gt;...

Смысл от выполнения async/await в синхронных методах
Привет всем! Текущая реализация фабрики не позволяет протянуть Task до...

Выполнение метода в отдельном потоке без await/async
В десктопном WPF проекте с .Net 4.0 необходимо сделать так: private void...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru