Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.95/37: Рейтинг темы: голосов - 37, средняя оценка - 4.95
 Аватар для arvalon
22 / 7 / 2
Регистрация: 26.10.2012
Сообщений: 212
Записей в блоге: 1

Простейшая прогамма с async/await нуждается в доработке

22.10.2015, 20:02. Показов 7196. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Облазил множество мануалов, всё равно не могу до конца понять как работать с async/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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
 
namespace GettingStarted
{
    class Program
    {
        static void Main(string[] args)
        {
            MyMethod();
        }
 
        public async static void MyMethod()
        {
            string res = await GetString();
        }
        public static void GetString()
        {
            Console.Write("abc");
        }
    }
}
Буду очень благодарен, если вы что-нибудь подправите!
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
22.10.2015, 20:02
Ответы с готовыми решениями:

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

Программа для сортировки одномерного массива нуждается в доработке
var A:array of integer; i, Res:integer; f:boolean; begin for i:=1 to 5 do begin write ('Элемент ', i,...

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

14
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
22.10.2015, 23:12
C#
1
2
3
4
5
static void Main(string[] args)
        {
            MyMethod();
            Console.ReadLine();
        }
Асинхронный метод сразу же возвращает.
После завершения работы Main программа закрывается.

А, ну и GetString измените со static void на static Task, из самого метода что-нибудь верните, вроде Task.Yield()
1
 Аватар для arvalon
22 / 7 / 2
Регистрация: 26.10.2012
Сообщений: 212
Записей в блоге: 1
23.10.2015, 13:00  [ТС]
Уже теплее, но осталась ошибка


Error CS1061 'string' does not contain a definition for 'GetAwaiter' and no extension method 'GetAwaiter' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)


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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
 
namespace GettingStarted
{
    class Program
    {
        static void Main(string[] args)
        {
            MyMethod();
            Console.ReadLine();
        }
 
        public static async void MyMethod()
        {
            string result= await myAwaitMeth();
        }
 
        public static string myAwaitMeth()
        {
            Thread.Sleep(5000);
            return "abc";
        }
    }
}
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
23.10.2015, 15:03
Цитата Сообщение от arvalon Посмотреть сообщение
осталась ошибка
Если у вас метод помечен как async, то у него может быть ровно три возможных возвращаемых значения:

1. void. Используется, если метод будет вызываться по принципу "запустил и забыл", например если это обработчик события.
C#
1
2
3
4
5
6
7
8
async void Foo()
{
   Console.Write("Minding my own business");
}
 
Action doSomething = Foo;
doSomething();
Console.WriteLine("Fire and forget");
2. Task. Используется, если метод не возвращает никакого значения, но в точке вызова должна быть возможность подождать его завершения:
C#
1
2
3
4
5
6
7
8
async Task Foo()
{
   Console.WriteLine("I don't return anything, but you can wait for me to finish");
   await Task.Delay(5000);
}
 
await Foo();
Console.WriteLine("Foo is done at this point");
3. Task<T>, где Т — тип возвращаемого значения. Используется, естественно, если метод возвращает значение:
C#
1
2
3
4
5
6
7
8
9
async Task<string> Foo()
{
   Console.WriteLine("Hang on, getting my string ready...");
   await Task.Delay(5000);
   return "Done!";
}
 
string result = await Foo();
Console.WriteLine("Foo returned '{0}'", result);
В вашем случае MyMethod ничего не возвращает и его никто не ждет, потому он может быть void.
А вот метод myAwaitMeth возвращает строку, значит тип его возвращаемого значения должен быть Task<string>.
И, кстати, не используйте Thread.Sleep в асинхронных методах — они могут отработать в том же потоке, откуда вызываются. Используйте вместо этого Task.Delay:
C#
1
2
3
4
5
        public static async Task<string> myAwaitMeth()
        {
            await Task.Delay(5000);
            return "abc";
        }
Добавлено через 4 минуты
Стоит добавить, что если в асинхронном методе в свою очередь ничего не надо ожидать через await, то его не обязательно помечать как async — достаточно венуть любой Task:
C#
1
2
3
4
5
6
7
8
Task Foo()
{
   Console.WriteLine("I don't return anything, but you can wait for me to finish");
   return Task.Delay(5000);
}
 
await Foo();
Console.WriteLine("Foo is done at this point");
То же самое, что второй пункт выше.
1
 Аватар для arvalon
22 / 7 / 2
Регистрация: 26.10.2012
Сообщений: 212
Записей в блоге: 1
23.10.2015, 15:33  [ТС]
Спасибо большое!
Запустил всё вместе, вот что получилось:
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
namespace Task_from_cyberforum
{
    class Program
    {
        static void Main(string[] args)
        {
            Foo();
            Console.WriteLine("Next job");
            FooTask();
            FooWithRetult();
            //string result=await FooWithResult(); // Так не работает.
            //await FooWithResult(); // Это тоже работает.
            Console.ReadKey();
        }
 
        static async void Foo()
        {
            Console.WriteLine("Foo");
        }
 
        static async Task FooTask()
        {
            await Task.Delay(4000);
            Console.WriteLine("FooTask is over");
        }
 
        static async Task<string> FooWithResult()
        {
            await Task.Delay(4000);
            Console.WriteLine("FooWithResultis over");
            return "FooWithParam";
        }
    }
}
Не могу понять как в методе Main в итоге вытащить string из FooWithResult(). Закомментировал 2 строки. Обе они вызывают ошибку


Severity Code Description Project File Line
Error CS4033 The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'
0
 Аватар для LeniumSoft
1454 / 847 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
23.10.2015, 16:17
Цитата Сообщение от arvalon Посмотреть сообщение
Не могу понять как в методе Main в итоге вытащить string из FooWithResult().
Из Main это легче так заюзать:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    public static void Main(string[] args)
    {
        var task = GetString();
        task.Wait();
 
        var line = task.Result;
 
        Console.WriteLine(line);
 
        Console.ReadLine();
    }
 
    public static Task<string> GetString()
    {
        return Task.FromResult("Привет!");
    }
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
23.10.2015, 17:40
Цитата Сообщение от LeniumSoft Посмотреть сообщение
C#
1
2
task.Wait();
var line = task.Result;
task.Wait можно выбросить — обращение к Result заблочит поток до конца выполнения.
1
 Аватар для LeniumSoft
1454 / 847 / 150
Регистрация: 06.06.2012
Сообщений: 2,370
23.10.2015, 23:25
Цитата Сообщение от kolorotur Посмотреть сообщение
task.Wait можно выбросить — обращение к Result заблочит поток до конца выполнения.
Действительно. Не часто async/await юзаю из консоли. Сорри...
0
Заблокирован
23.10.2015, 23:45
мне вот самому интересно стало, допустим длинное копирование большого файла:
C#
1
2
3
4
async static void Copy(string source, string dest)
        {
            File.Copy(source, dest);
        }
но не получается так, поток зависает все равно на все копирование, а если await поставить переде File то ошибка будет

Добавлено через 2 минуты
эти async / await они вообще как работают? они что неявно создают отдельный поток и в нем выполняют эту функцию?
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,574
23.10.2015, 23:54
C#
1
2
3
4
        async static void Copy(string source, string dest)
        {
            await Task.Factory.StartNew(() => File.Copy(source, dest));
        }
А если так?
1
Заблокирован
24.10.2015, 09:10
Someone007, кажется работает, и все таки я так и не понял как
0
 Аватар для arvalon
22 / 7 / 2
Регистрация: 26.10.2012
Сообщений: 212
Записей в блоге: 1
27.10.2015, 11:41  [ТС]
Всем большое спасибо за ответы!

Хотелось бы уточнить некоторые, видимо очевидные вещи, но я явной форме о которых я не смог нигде прочитать.

1. Первое, значит так, как я понимаю, вот мы по ходу кода хотим что бы задача выполнилась асинхронно. Тогда мы объявляем Task, пихаем в него какой-нибудь свой метод (лямбда-выражение или полноценный метод, без return чего либо, с Task или с Task<TResult>, не суть). Всё норм, таск выполняется в каких-то других потоках, не вешая основной, в котором был вызван (преимущественно UI, но может быть что угодно). Ключевых слов async и await тут не используется!

2. Второе. Вот мы объявляем метод async. Как сказано в примере 1 от kolorotur:
C#
1
2
3
4
5
6
7
8
async void Foo()
{
   Console.Write("Minding my own business");
}
 
Action doSomething = Foo;
doSomething();
Console.WriteLine("Fire and forget");
Как я понял, это будет ТОЖЕ САМОЕ, что и мой пункт 1 выше? Только вызов будет оформлен в отдельный метод. Класс Task тут явно не объявляется, но internal будет он же?

3. Ключевое слово await. Как я понял если я хочу что бы было асинхронное выполнение моего метода(ов), но хочу, что бы основной код, откуда был вызван async метод, ждал выполнения этого метода (или его сбоя, или получения cancellationToken). Т.е. распараллеливание будет, но основой поток, откуда был вызван async - будет висеть и ждать? Пока в теле async-метода не выполнится какой-нибудь statement с пометкой await. И тут ими можно будет в добавок поуправлять синхронизацией с помощью Continiouswith(), AwaitAll, AwaitAny как требует моя логика приложения. Всё так?
И класс task тут опять явно не объявляется.
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
27.10.2015, 12:36
Цитата Сообщение от arvalon Посмотреть сообщение
таск выполняется в каких-то других потоках
Не обязательно!
Таск может выполниться и в текущем потоке, но когда-нибудь потом, а не прямо сейчас.
А может и прямо сейчас, что по сути будет синхронным выполнением.
В этом главное различие между асинхронным и параллельным выполнением: суть асинхронного выполнения в том, чтобы не блокировать текущий поток, то есть не оставлять его без дела.

Цитата Сообщение от arvalon Посмотреть сообщение
это будет ТОЖЕ САМОЕ, что и мой пункт 1 выше? Только вызов будет оформлен в отдельный метод. Класс Task тут явно не объявляется, но internal будет он же?
Да, этот код будет выглядеть примерно так:
C#
1
2
3
Action doSomething = Foo;
Task.Run(doSomething);
Console.WriteLine("Fire and forget");
Цитата Сообщение от arvalon Посмотреть сообщение
Как я понял если я хочу что бы было асинхронное выполнение моего метода(ов), но хочу, что бы основной код, откуда был вызван async метод, ждал выполнения этого метода (или его сбоя, или получения cancellationToken). Т.е. распараллеливание будет, но основой поток, откуда был вызван async - будет висеть и ждать?
Распараллеливание тут может будет, а может и не будет — смотрите выше. Вообще при обсуждении асинхронных методов лучше забудьте слово "поток".
Если в основном потоке имеется await, то либо асинхронное действие завершается тут же (синхронно) и метод продолжает свою работу, либо метод завершает задачу и продолжает ее, когда закончится асинхронное выполнение.

Если у вас в коде есть примерно такая конструкция:
C#
1
2
3
4
5
6
async void Foo()
{
  // Что-то делаем
  await DoSomething();
  // Что-то еще делаем
}
То она трансформируется компилятором примерно в такую:
C#
1
2
3
4
5
6
7
8
9
10
11
12
void Foo()
{
   // Что-то делаем
   Task task = DoSomething();
   var awaiter = task.GetAwaiter();
   awaiter.OnCompleted(ContinuationCallback);
}
 
void ContinuationCallback()
{
   // Что-то еще делаем
}
То есть весь код, который находится после await выносится в отдельный метод с захватом локальных переменных, после чего этот метод выполняется по звершении асинхронной задачи.
Код становится чуть сложнее, если имеются возвращаемые значения, но суть остается та же: все, что после await выносится в отдельный метод, своего рода в обработчик события окончания асинхронной задачи.

Еще раз заостряю внимание на том, что неизвестно, в каком потоке будет выполнен метод DoSomething и ContinuationCallback: может быть в другом параллельно, а может быть в текущем когда-нибудь потом или прямо сейчас. Из-за этого лучше не мешайте вместе асинхронные методы и блокирующие операции — очень быстро можете схлопотать дедлок.
0
 Аватар для arvalon
22 / 7 / 2
Регистрация: 26.10.2012
Сообщений: 212
Записей в блоге: 1
20.11.2015, 13:56  [ТС]
А вот пример из учебника Nagel C., Glynn J., Skinner M. - Professional C# 5.0 and .NET 4.5.1 (Programmer to Programmer), абзац Futures—Results from Tasks

When a task is finished, it can write some stateful information to a shared object. Such a shared object must
be thread-safe. Another option is to use a task that returns a result. Such a task is also known as future as it
returns a result in the future. With early versions of the Task Parallel Library (TPL), the class had the name
Future as well. Now it is a generic version of the Task class. With this class it is possible to define the type
of the result that is returned with a task.
A method that is invoked by a task to return a result can be declared with any return type. The following
example method TaskWithResult returns two int values with the help of a Tuple. The input of the
method can be void or of type object, as shown here (code file TaskSamples/Program.cs):
C#
1
2
3
4
5
6
7
8
static Tuple<int, int> TaskWithResult(object division)
{
Tuple<int, int> div = (Tuple<int, int>)division;
int result = div.Item1 / div.Item2;
int reminder = div.Item1 % div.Item2;
Console.WriteLine("task creates a result...");
return Tuple.Create<int, int>(result, reminder);
}
When defining a task to invoke the method TaskWithResult, the generic class Task<TResult> is used. The
generic parameter defines the return type. With the constructor, the method is passed to the Func delegate,
and the second parameter defines the input value. Because this task needs two input values in the object
parameter, a tuple is created as well. Next, the task is started. The Result property of the Task instance t1
blocks and waits until the task is completed. Upon task completion, the Result property contains the result
from the task:
C#
1
2
3
4
5
var t1 = new Task<Tuple<int,int>>(TaskWithResult,Tuple.Create<int, int>(8, 3));
t1.Start();
Console.WriteLine(t1.Result);
t1.Wait();
Console.WriteLine("result from task: {0} {1}", t1.Result.Item1,t1.Result.Item2);
Т.е. метод, считающий результат деления и остаток от деления запускается в Task. Ждём результат и выводим на экран. Всё понятно кроме Wait!
Зачем тогда строчка №5 t1.Wait(); во втором участке кода? Ведь как написал выше kolorotur
task.Wait можно выбросить — обращение к Result заблочит поток до конца выполнения.
Закомментировал её - тот же эффект выполнения и никаких ошибок.
Миниатюры
Простейшая прогамма с async/await нуждается в доработке  
0
Эксперт .NET
 Аватар для kolorotur
17823 / 12973 / 3382
Регистрация: 17.09.2011
Сообщений: 21,261
20.11.2015, 14:08
Цитата Сообщение от arvalon Посмотреть сообщение
Зачем тогда строчка №5 t1.Wait(); во втором участке кода?
В данном примере — низачем
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
20.11.2015, 14:08
Помогаю со студенческими работами здесь

Async await
Пытыюсь разобраться с async/await но что то без успешно пока. Не подскажете как переделать этот код на примере проще освоить public...

async/await
https://metanit.com/sharp/tutorial/13.7.php вот код Task&lt;T&gt;: // определение асинхронного метода static async...

Async/await
Мне нужно, чтобы пароль выводился по одному символу public Matrix() { InitializeComponent(); ...

Async/await
В интернете копался ничего информативного не нашел, все в каких- то не понятных для новичка терминах, объясните пожалуйста смысл...

async/await (._. )
Опять я с глупым вопросом. Не могу понять, почему метод, который выгружает данные не асинхронный? Вообще форма зависает на неопределенное...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru