Ожидает ли создать еще один поток? - PullRequest
1 голос
/ 08 апреля 2019

Я прочитал документ Microsoft об асинхронности и жду.Он говорит:

Асинхронные и ожидающие ключевые слова не приводят к созданию дополнительных потоков.

Но я запускаю следующий код

using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
    public class AsyncMain
    {
        static void Main()
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            Task task = Test();
            task.Wait();
        }

        public async static Task Test()
        {
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
            await Task.Delay(1000);
            Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
        }

    }
}

Результат:

1
1
4

Очевидно, что

await Task.Delay(1000);
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

выполняется в другом потоке,Почему в документе говорится, что нет созданного потока?

Я прочитал предыдущий вопрос Создает ли использование async / await новый поток? , но этоне отвечает на мой вопрос, ответ там просто скопировать пасты из источника Microsoft.Почему в моем тесте отображаются разные идентификаторы потоков?

Ответы [ 3 ]

8 голосов
/ 09 апреля 2019

Я всегда призываю людей прочитать мое async вступление и следовать async рекомендациям .В итоге:

await по умолчанию захватывает «контекст» и возобновляет выполнение метода async в этом контексте.В этом случае контекст является контекстом пула потоков.Поэтому вы видите, что Test возобновляет выполнение в потоке пула потоков.

async и await сами по себе не создают никаких дополнительных потоков;например, если вы сделаете то же самое в приложении пользовательского интерфейса, «контекст» будет потоком пользовательского интерфейса, и Test возобновит выполнение в этом потоке пользовательского интерфейса.Но контекст, который неявно захвачен await, отвечает за планирование продолжения asnc, и контекст в этом примере просто планирует его для пула потоков.

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

В вашем тесте вы видите разные идентификаторы потоков, потому что для выполнения вашего кода использовались разные потоки.Это не означает, что async / await вызвало создание дополнительных потоков.В этом случае используемые потоки уже существовали в пуле потоков, называемом пулом потоков.

Существует две разные идеи:

  • задачи, представляющие работу, которую нужно выполнить, и
  • как задачи фактически обрабатываются (например, запланированы и выполнены)

Асинхронное / ожидание относится к первому, но ваш тестовый код говорит вам кое-что о втором: конкретный механизм, с помощью которого эти задачи были обработаны.

Механизм определяется контекстом.Некоторые контексты используют более одного потока (но учтите, что именно контекст решает, как он управляет этими потоками, в том числе и когда он создает новые), но некоторые используют только 1 поток.

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

0 голосов
/ 09 апреля 2019

Я немного изменил ваш пример:

public async static Task Test()
{
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    await Task.CompletedTask; // <--- instead of Task.Delay()
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
}

Теперь вывод равен 1, 1, 1.

await не создает новый поток.Task.Delay является виновником!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...