Прочитал несколько источников про async/await, где писалось, что якобы никаких дополнительных потоков эти конструкции не создают.
Решил написать тестовый код:
public static void Main()
{
var t = Test();
t.Wait();
}
static async Task Test()
{
var t = Test2();
for (; ; )
{
await Task.Delay(1000);
Console.WriteLine("0");
}
}
static async Task Test2()
{
for (; ; )
{
await Task.Delay(1000);
Console.WriteLine("1");
}
}
Так вот, Visual Studio показывает, что было создано 2 потока.
А иногда, если верить дебагеру, их 3.
Как так?
Или все таки потоки не создаются при использовании только IO операций, а при каких-то вычислительных потоках CLR определяет необходимость создания потока?
Или под "не создает потоков" понималось, что берутся готовые потоки из пула, но множество потоков в программе в единицу времени имеет место быть?
Или имеется в виду, что старается использовать, как можно меньше потоков? Так если крутится 2 асинхронных операции и они не пресекаются по времени выполнения, то используется 1 поток, а если они параллельно крутятся, то CLR выгодно 2 потока крутить?
Главный поток у вас висит на операции t.Wait();
и ничего не выполняет.
Вы не установили контекст синхронизации - а потому все продолжения await выполняются в пуле потоков. Отсюда и второй поток - для того чтобы выполнять вывод в консоль. А если обе задачи просыпаются одновременно - то нужен и третий поток.
Тем не менее, как вы можете заметить, Task.Delay(1000)
сам по себе ни в каком потоке не выполняется - потоки нужны только для вывода в консоль. Если вы запустите десять тысяч подобных задач - им для выполнения будет достаточно относительно небольшого числа потоков. В этом и выгода.
Кстати, способ избавиться от дополнительных потоков - есть, но для этого надо избавиться от вызова .Wait()
и поставить какой-нибудь контекст синхронизации.
Например, можно взять QueueSynchronizationContext из моего ответа на вопрос "Зависает оператор await
в оконном приложении / программа висит при вызове Task.Result или Wait". Вот такой код будет выполняться строго в одном потоке:
public static void Main()
{
var syncCtx = new QueueSynchronizationContext();
// вызывает внутри SynchronizationContext.SetSynchronizationContext(syncCtx);
var t = Test(); // Важно: вызывать строго после SetSynchronizationContext
syncCtx.WaitFor(t);
}
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Виртуальный выделенный сервер (VDS) становится отличным выбором
здравствуйте, пытаюсь понять что такое шина данных/шина сообщений(message bus) в распределенных системах
ЗдравствуйтеУ меня скрипт через ajax подгружает html контент
Есть 2 блока, где нужно событие keydown они на разных экранах страницы, keydown общийКак его ограничить, чтобы если видна одна область, то работает...
Подскажите, есть такая функция которая вызывается в VueJS следующим образом событие myEvent возвращает результат (result) при вызове: