На данный вопрос уже ответили:
Нужен async/await или не нужен?
5 ответов
Здравствуйте, извиняюсь за вопрос по этой теме т.к существует довольно огромное количество статей об этих ключевых словах, но возможно такое количество статей и ввело меня в некое не до понимание.
Я просто хочу узнать правильно ли я все понял и задать походу пару вопросов.
Начнем с async. Метод помеченный async разрешает нам внутри данного метода использовать await и требует что бы возвращаемый тип имел метод GetAwaiter.
Ключевое слово await. Await ставится перед операцией которая выполняется во вторичном потоке. Он позволяет не дожидаться пока вторичный поток (IO или обычный Thread) закончит свое выполнение. Await просто оборачивает то, что идет после await в отдельный метод, который по callback вызывается когда отработает вторичный поток. Тем самым первичный поток продолжает выполняться дальше. А когда отработает вторичный поток из пула потоков возьмется рандомный поток который довыполняет вторую часть метода.
В итого что это дает в приложениях
в приложениях с ui потоками(не до конца понятно что за ui поток, работаю исключительно asp.net) наш поток продолжит выполнение и не заблочит действия пользователя;
в asp.net mvc у меня первичный поток освободится и будет работать только вторичный;
и последнее синтаксический сахар который скрывает всю логику которая это делает.
Вопросы
Правильно ли я все описал, действительно ли в этом смысл async await(разбить метод на две части и до выполнять вторую часть как callback, тем самым не задерживая первичный поток)?
Что за метод configureawait?
Почему многие говорят что эти ключевые слова не связаны с потоками. Ну как же await то ставится перед операцией, которая будет выполняться во вторичном потоке, да и суть то в чем, это конструкция была придумана что бы не держать первичный поток. Так что связь тут самая прямая или я не прав?
Когда закончится выполняться вторичный поток, какой поток продолжит выполнять вторую часть метода. Тот самый вторичный поток? Или будет взят любой поток из thread pool?
Ответ
Для начала, ваши предположения.
Ну как бы технически говоря да. Но есть ещё одна важная для понимания вещь: с ключевым словом async функция разбиваются на куски так, что между этими кусками функция вообще нигде не бежит. А каждый из кусков выполняется синхронно, как обыкновенная функция. Границы этих кусков идут по await
«Await ставится перед операцией которая выполняется во вторичном потоке.» — это неверно, await означает лишь, что в этой точке функция прекращает выполнение, и возобновляется тогда, когда Task, по отношению к которому производится await, завершается.
Task, как мы уже видели, вовсе не означает «кусок кода, бегущий в каком-то потоке». Например, async-функция производит Task, который бежит в конкретном потоке лишь иногда, кусками.
Теперь, ваши вопросы.
В общем и целом правда, но не на одну часть, а на много. Представьте себе, например, такой код:
async Task PrintSlowly(IEnumerable
В этом методе у нас k + 1 кусок, где k — количество элементов, полученных из IEnumerable
async Task Weird()
{
if (Math.Sin(0) == 42)
await Task.Delay(1000);
for (int x = 0; x < 1_000_000; x++)
for (int y = 0; y < 1_000_000; y++)
for (int z = 0; z < 1_000_000; z++)
{
if (x * x * x * x + y * y * y * y == z * z * z * z)
throw new Exception("Ферма лох");
}
}
Где и как выполняется Task, определяется исключительно самим Task'ом. Единственный случай, когда Task целиком выполняется на побочном потоке, есть Task, запущенный через Task.Run() (в этом случае поток берётся из пула потоков). В остальных случаях забота о том, где именно выполняться, лежит на самом Task'e, async/await этим не занимается, и даже не требует, чтобы Task вообще где-то выполнялся. Task должен бы завершаться, это да (и то не обязан), а выполняться он может вообще нигде. Вот пример:
static Task WaitTimer()
{
var tcs = new TaskCompletionSource
И да, обязательно почитайте ответы к этому вопросу
Комментариев нет:
Отправить комментарий