На данный вопрос уже ответили:
Здравствуйте, извиняюсь за вопрос по этой теме т.к существует довольно огромное количество статей об этих ключевых словах, но возможно такое количество статей и ввело меня в некое не до понимание.
Я просто хочу узнать правильно ли я все понял и задать походу пару вопросов.
В итого что это дает в приложениях
Вопросы
Для начала, ваши предположения.
Ну как бы технически говоря да. Но есть ещё одна важная для понимания вещь: с ключевым словом async
функция разбиваются на куски так, что между этими кусками функция вообще нигде не бежит. А каждый из кусков выполняется синхронно, как обыкновенная функция. Границы этих кусков идут по await
.
«Await ставится перед операцией которая выполняется во вторичном потоке.» — это неверно, await
означает лишь, что в этой точке функция прекращает выполнение, и возобновляется тогда, когда Task
, по отношению к которому производится await
, завершается.
Task
, как мы уже видели, вовсе не означает «кусок кода, бегущий в каком-то потоке». Например, async
-функция производит Task
, который бежит в конкретном потоке лишь иногда, кусками.
Теперь, ваши вопросы.
В общем и целом правда, но не на одну часть, а на много. Представьте себе, например, такой код:
async Task PrintSlowly(IEnumerable<int> data)
{
Console.WriteLine("begin");
foreach (var n in data)
{
await Task.Delay(1000);
Console.WriteLine(data);
}
Console.WriteLine("end");
}
В этом методе у нас k + 1
кусок, где k
— количество элементов, полученных из IEnumerable<int>
.
Если await
выполняется в UI-потоке (или в любом потоке, в котором есть свой TaskScheduler
/SynchronizationContext
), то следующий кусок функции перебрасывается для выполнения в тот же поток/SynchronizationContext
. Если же вам это не нужно, вы можете сказать ConfigureAwait(false)
, что означает «мне безразлично, в каком контексте выполнятся остальные куски async
-функции». При этом рантайм может заставить их выполняться где угодно, гарантий нет.
Нет, операция, на которую делается await
, не обязательно будет выполняться в другом потоке. Task
не есть «кусок кода, который выполняется где-то ещё». Если эта операция реально не блокирует текущий поток, то да, текущий поток будет свободен. Но вы легко можете написать Task
, который будет блокировать текущий поток:
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<int>();
new System.Threading.Timer(o => tcs.SetResult(0), null, 3000,
System.Threading.Timeout.Infinite);
return tcs.Task;
}
И да, обязательно почитайте ответы к этому вопросу.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Здравствуйте, как правильно открывать файл в pictureBox и правильно закрывать его для перезаписывания файла
Только только начал изучать ASPNET -> пишу приложение с возможностью регистрации и входа через обычную html форму
Вот есть кодКогда нажиму на клавишу, куб должен появляться, а когда отпускаю пропадать, но ничего не выходит