Объясните как работает await с CPU и IO bound операциями

Где и как будут выполнены методы DoCPUBoundOperation и DoIOBoundOperation? На сколько мне известно для IO Bound операций не нужны потоки и они выполняются в "пространстве ядра"(kernel space). В свою очередь CPU Bound операция выполняются "на CPU", поэтому требуют собственный поток. Опишите пожалуйста порядок как будет происходит процесс выполнения кода ниже.

static async Task Main(string[] args)
{
    var cpuResult = await DoCPUBoundOperation();
    var ioResult = await DoIOBoundOperation();

    Console.WriteLine($"cpuResult = {cpuResult}, ioResult = {ioResult}");
    Console.ReadKey();
}


public static async Task<string> DoIOBoundOperation()
{
    var client = new WebClient();
    var uri = new Uri("http://someAdress");

    return await client.DownloadStringTaskAsync(uri);
}

public static  Task<int> DoCPUBoundOperation()
{
    var sum = 0;
    for (int i = 0; i <= 10; i++)
    {
        sum += i;
    }

    Thread.Sleep(10000);
    return Task.FromResult(sum);
}

Ряд вопросов которые нуждаются в отдельном внимании

  1. После попадания внутрь метода DoIOBoundOperation, в каком потоке будет выполняться кусок кода
 var client = new WebClient();
 var uri = new Uri("http://someAdress");
  1. В месте вызова

    var ioResult = await DoIOBoundOperation();
    

для выполнения DoIOBoundOperation метода будет выделен отдельный поток? И если да, то поток возьмется из пула потоков?


Ответы (1 шт):

Автор решения: tym32167

1)После поподания внутрь метода DoIOBoundOperation, в каком потоке будет выполняться кусок кода

В методе

   public static async Task<string> DoIOBoundOperation()
   {
       var client = new WebClient();
       var uri = new Uri("http://someAdress");

       return await client.DownloadStringTaskAsync(uri);
   }

Асинзронная только последняя операция. То есть всё, что до этой операции выполняется синхронно, как в обычном методе.

  1. В месте вызова var ioResult = await DoIOBoundOperation(); для выполнения DoIOBoundOperation метода будет выделен отдельный поток?И если да, то поток возьмется из пула потоков?

Асинхронный != многопоточный. Поток может быть создан, а может и нк быть создан. Для IO операций потоки не создаются, то есть для самой операции поток не нужен. Но вот рассмотрим следующий код

{код 1}
await IO operation
{код 2 - называется код-продолжение}

так вот код до асинхронной операции и код после асинзроннорй операции могут выполняться в одном и том же потоке или в разных потоках.

Например, если вы выполняете этот код в UI приложении в UI потоке, у которого есть контекст синхронизации, то обе части кода будут выполнены в одном потоке - в UI потоке.

Но в консольном приложении или если запустить этот код в потоке без контекста, то вторая часть может вернуться в поток, а может выполняиться в другом потоке из пула потоков.

Немного инфы тут.

Что касается DoCPUBoundOperation- то этот код не является асинхронным. Это обычный синхронный код.

→ Ссылка