0

I have read some docs, and what I learned is that await Task.Delay(1000) does not block thread.

But in this code example, it seems that it blocks threads:

       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();

it prints:

 ====== 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()

as per the print out, it executes the code in a sync way.

I thought it would print some thing like below:

 ====== 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()

So I'm confused, could somebody please explain the behavior? Thanks.

Ivan Glasenberg
  • 29,865
  • 2
  • 44
  • 60
  • [FYI](https://github.com/microsoft/referencesource/blob/master/mscorlib/system/threading/Tasks/Task.cs#L5863-L5902) – ProgrammingLlama Mar 25 '20 at 06:40
  • 9
    You seem to be confusing two different things. Waiting for a process to be completed before continuing doesn't necessarily equal blocking the thread. When you use `await AnyTrueAsyncMethod();`, the thread isn't blocked, however, the next line doesn't get executed until the task is finished. – 41686d6564 stands w. Palestine Mar 25 '20 at 06:42
  • [Related question](https://stackoverflow.com/questions/52863940/does-task-delay-make-sense-on-a-dedicated-thread) – ProgrammingLlama Mar 25 '20 at 06:44
  • Which threads do you believe that are blocked? The threads with id 3 and 4? You can test your assumption by starting a second task that will run concurrently with this one and does some similar thing, to see if the threads 3 and 4 will appear in the logs of the other task. If they do, then they are not blocked. – Theodor Zoulias Mar 25 '20 at 06:56
  • @AhmedAbdelhameed, can you please explain a little more? Thanks. – Ivan Glasenberg Mar 25 '20 at 07:03
  • 1
    [There is no thread](https://blog.stephencleary.com/2013/11/there-is-no-thread.html) – Fildor Mar 25 '20 at 07:06
  • 1
    @IvanYang Your code is no executed doesn't means current thread is "blocked". See https://stackoverflow.com/a/34706101/4123703 – Louis Go Mar 25 '20 at 07:08

1 Answers1

4

inside new Task()

First, I have to say: never, ever use the Task constructor. There are exactly zero valid use cases. If you want to run a delegate on a thread pool thread, use Task.Run.

So I'm confused, could somebody please explain the behavior?

Yes, the key is that there's a difference between "imperative" (one step after another) and "synchronous" (blocking the caller).

as per the print out, it executes the code in a sync way.

No, it is not synchronous at all. It is, however, imperative. When an await decides it needs to wait, it will "pause" its current method and return to the caller. When that await is ready to continue, it will resume executing its method.

Note that the thread is not blocked. The method is paused. So it is imperative but not synchronous.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810