Вызывает ли асинхронный метод немедленный запуск его команд - PullRequest
0 голосов
/ 15 мая 2019

Я получил этот код:

static async Task AsynchronousProcessing()
{  
    Task<string> t1 = GetInfoAsync("Task 1", 3);  
    Task<string> t2 = GetInfoAsync("Task 2", 5);  
    string[] results = await Task.WhenAll(t1, t2);  
    foreach (string result in results)  
    {    
      WriteLine(result);  
    }
}

static async Task<string> GetInfoAsync(string name, int seconds)
{  
    await Task.Delay(TimeSpan.FromSeconds(seconds));   
    return  "hi";
}

При достижении строки Task<string> t1 = GetInfoAsync("Task 1", 3); будет ли он уже запускаться асинхронно с await Task.Delay(TimeSpan.FromSeconds(seconds)); и переходить к остальной части метода, или он сразу же вернет задачу, фактически не запуская ее?

А если он не запустится при вызове метода, будут ли задачи запускаться только при вызове Task.WhenAll(t1,t2)? Поскольку, если это не начнется сразу, я бы ожидал, что GetInfoAsync сделает что-то вроде return new Task<string>(() => ...);

Ответы [ 2 ]

3 голосов
/ 15 мая 2019

Рекомендую прочитать мое async вступление .

В итоге все async методы начинают выполняться синхронно. Поэтому, когда AsynchronousProcessing вызывает GetInfoAsync, GetInfoAsync начинает работать синхронно, как и любой другой метод. Метод async может стать асинхронным, если есть await. В этом случае GetInfoAsync вызывает Task.Delay (опять же, синхронно, как обычный вызов метода), а затем передает Task в await. На этом этапе await изучит задачу; если он уже завершен, он продолжит работать синхронно; в противном случае он будет работать асинхронно и вернет незавершенную задачу из GetInfoAsync.

Выполняются задачи, возвращенные методами async. Я обычно не использую термин «выполняется», потому что они на самом деле не запускают код на процессоре и потому что статус задачи на самом деле не Running. Это состояние "асинхронного выполнения", к сожалению, называется WaitingForActivation (хотя оно ничего не ждет).

Так как, если он не запустится сразу, я ожидаю, что GetInfoAsync сделает что-то вроде return new Task (() => ...);

Ключевое слово async управляет созданием задачи. Как отмечено выше, задачи являются «горячими» или «в процессе». Это не то же самое, что «запуск» или «запуск», оба из которых подразумевают задачи, выполняющие код процессора. Существует два типа задач: задачи, которые я называю делегатом, и задачи обещания . Те, которые возвращены из async методов, являются Обещанием.

Если новых потоков с await нет, то как они будут работать параллельно?

Они запускаются одновременно (не в параллельно , поскольку на задержке не заблокирован дополнительный поток).

Однако, когда await Task.Delay(..) завершится, возможно, будет использован другой поток. await возобновит в своем захваченном контексте и выполнит return "hi"; в этом контексте. Если захваченный контекст является контекстом пула потоков, то эта одна строка кода будет выполняться в потоке пула потоков. Конечный автомат async преобразует return в код, который завершает задачу, ранее возвращенную этим методом async.

0 голосов
/ 15 мая 2019

GetInfoAsync вызывается и работает синхронно, как обычно, пока не достигнет линии await Task.Delay(TimeSpan.FromSeconds(seconds)). Затем он возвращает незавершенную задачу обратно в вызывающий метод AsynchronousProcessing().

Итак, да, задача действительно запускается при вызове метода, т. Е. Вам не нужно ждать GetInfoAsync для вызова метода Task.Delay.

...