Ожидает ли Task.Delay (1000) внутри нового Task () какой-либо поток? - PullRequest
0 голосов
/ 25 марта 2020

Я прочитал несколько документов, и я узнал, что await Task.Delay(1000) не блокирует поток.

Но в этом примере кода кажется, что он блокирует потоки:

       var task = new Task(async () => {
                Console.WriteLine(" ====== begin Delay()");
                for (int i = 1; i < 5; i++)
                {
                    Console.WriteLine(" ===Delay=== " + i);
                    Console.WriteLine("the task thread id: " + Thread.CurrentThread.ManagedThreadId + "; the task id is: " + Task.CurrentId);
                    await Task.Delay(1000);
                    Console.WriteLine("**ddd***:"+i);
                }

                Console.WriteLine(" ====== end Delay()");

            });

            task.Start();

он печатает:

 ====== begin Delay()
 ===Delay=== 1
the task thread id: 3; the task id is: 1
**ddd***:1
 ===Delay=== 2
the task thread id: 4; the task id is:
**ddd***:2
 ===Delay=== 3
the task thread id: 3; the task id is:
**ddd***:3
 ===Delay=== 4
the task thread id: 4; the task id is:
**ddd***:4
 ====== end Delay()

в соответствии с распечаткой, он выполняет код в формате c.

Я думал, что это напечатает что-то вроде следующего:

 ====== begin Delay()
 ===Delay=== 1
the task thread id: 3; the task id is: 1    
 ===Delay=== 2
the task thread id: 4; the task id is:    
 ===Delay=== 3
the task thread id: 3; the task id is:    
 ===Delay=== 4
the task thread id: 4; the task id is:    
**ddd***:1
**ddd***:2
**ddd***:3
**ddd***:4
 ====== end Delay()

Так что я запутался, может кто-нибудь объяснить, пожалуйста, поведение? Спасибо.

1 Ответ

5 голосов
/ 25 марта 2020

внутри новой задачи ()

Сначала я должен сказать: никогда, никогда использовать конструктор Task . Есть ровно ноль действительных вариантов использования. Если вы хотите запустить делегат в потоке пула потоков, используйте Task.Run.

Так что я запутался, может кто-нибудь объяснить, пожалуйста, поведение?

Да ключ в том, что есть разница между «императивом» (один шаг за другим) и «синхронным» (блокировка вызывающего абонента).

согласно распечатке, он выполняет код синхронно c way.

Нет, это совсем не синхронно. Это, однако, обязательно. Когда await решит, что ему нужно подождать, он "приостановит" свой текущий метод и вернется к вызывающей стороне. Когда этот await готов продолжить, он возобновит выполнение своего метода.

Обратите внимание, что поток не заблокирован. Метод приостановлен. Так что это обязательно, но не синхронно.

...