4

I read many articles said that async/await doesn't create additional threads. But the message from Output and Thread windows in debug mode of Visual Studio said the contrary.

I created a very simple example windows form with some code;

private void button2_Click(object sender, EventArgs e)
{
    Task t = methodAsync();
    //t.Wait();
}
async Task methodAsync()
{
    Console.WriteLine($"==before DownloadStringTaskAsync");
    using (var wc = new System.Net.WebClient())
    {
        string content = await wc.DownloadStringTaskAsync("https://stackoverflow.com");
    }
    Console.WriteLine($"==after DownloadStringTaskAsync");
}

I start app in debuging mode, I pause it by clicking pause button on Debug toolbar. Threads windows show there is only one Main thread, that's normal so far.

enter image description here

Then I click on button to execute methodAsync. When it complete DownloadString, I pause app again, and then I see serveral additional thread in Thread windows.

enter image description here

After about 10 seconds the Output windows shows message "The thread xxx has exited with code 0 (0x0)".

enter image description here

The same result when I replace WebClient.DownloadStringTaskAsync with await Task.Delay(xxx) I wonder if async/await does really create new thread or not.

Any explaination?

KevinBui
  • 880
  • 15
  • 27
  • 2
    Async work will usually run on a different thread but it will resume on the original thread if you do not ConfigureAwait(false). It is grabbing a thread from the pool. I'm not sure if that is what you mean by "creating a thread". – Crowcoder Jan 21 '18 at 12:48
  • 1
    What you’ve read and what you’ve understood are not necessarily the same thing. `await-async` does not automatically mean run this task in a “new thread”, in some casss it does in some it doesn’t. The idea to get across is that asynchronous is not the same as concurrent on another thread. – InBetween Jan 21 '18 at 12:55
  • 1
    @Fabjan that is not true always. Not all asynchronous task need to run on a thread from the thread pool. Take a look at [there is no thread](https://blog.stephencleary.com/2013/11/there-is-no-thread.html) for an interesting read. – InBetween Jan 21 '18 at 13:00
  • If you are not already aware, checkout The Debug > Windows > Tasks pane. – Crowcoder Jan 21 '18 at 13:08
  • 1
    @fabjan that’s besides the point, your affirmation is incorrect and I was merely pointing it out. – InBetween Jan 21 '18 at 13:10
  • Possible duplicate of [Asynchronous vs Multithreading - Is there a difference?](https://stackoverflow.com/questions/600795/asynchronous-vs-multithreading-is-there-a-difference) – Fabjan Jan 21 '18 at 14:34
  • @InBetween A quote from Stephen Cleary's blog: "...one of the I/O threads in the thread pool. The ThreadPool keeps a number of threads registered in its IOCP; these are different than the worker threads that most people associate with the ThreadPool. The ThreadPool manages both worker thread and I/O threads...", so still there is a *thread* somewhere, no matter if it's an IOCP or a worker thread it's still a thread in which context an async operation is executed... – Fabjan Jan 21 '18 at 14:38
  • Asynchronous call is a call where calling thread doesn't wait for operation to be completed and operation is executed elsewhere (not in a calling thread)... – Fabjan Jan 21 '18 at 14:51
  • @fabjan I see you managed to absolutely miss the point of the article to somehow score a point here... That blog is quoted by SO users that actually *wrote* the async-await feature into the compiler to precisely point out that there isn’t always a thread involved... but to each his own, draw whatever conclusions you see fit from the article. – InBetween Jan 21 '18 at 14:56
  • @InBetween Please read carefully comments under the article that you've so kindly provided. Stephen wrote there that for an I/O async operation there is an IOCP thread involved (which he says is a different kind of thread) and no worker thread involved... And yes, there is no guarantee that an async operation requires a thread however there is no guarantee that it won't require one. – Fabjan Jan 21 '18 at 15:08
  • @fabjan the thread you are talking about is taken briefly *to signal the task is done*! The whole point is that the asynchronous task itself is not executed in another thread! The async copy could have taken 10 minutes, those 10 minutes are executed with no threads except the last few ms it takes to signal the task is finished. If this qualifies as not contradicting your original affirmation (you’ve deleted by the way), well, good for you. – InBetween Jan 21 '18 at 15:36
  • @InBetween Ok, I think that we've said enough about it. Thanks for the article though. Btw Stephen is one of developers that I admire. – Fabjan Jan 21 '18 at 15:45
  • I already read article of Stephen and others. They said almost asynchronous I/O don't use a thread (stackoverflow.com/a/37419845/836376). Do you know any API in .NET Framework like that? If you do, show me one! – KevinBui Mar 18 '18 at 08:49

2 Answers2

1

async and await are just keywords that make a method awaitable, and then allow you to asynchronously wait for it and resume execution. Tasks are the underlying framework elements that represent the asynchronous result of the execution of the method, and the TaskScheduler is responsible for coordinating the execution of Tasks, which may involve using the Thread Pool, creating new threads, etc. The default Task Scheduler on Windows generally uses the Thread Pool to execute tasks.

Aaron M. Eshbach
  • 6,380
  • 12
  • 22
0

The WebClient.DownloadStringTaskAsync method uses Task-based Asynchronous Pattern and uses resource thread resources that are automatically allocated from the thread pool.

When you implement a TAP method, you can determine where asynchronous execution occurs. You may choose to execute the workload on the thread pool, implement it by using asynchronous I/O (without being bound to a thread for the majority of the operation’s execution), run it on a specific thread (such as the UI thread), or use any number of potential contexts.

As you can see in the method definition, it has an attribute ExternalThreading = true signalizing that it might allocate resources on external threads.

Raul
  • 2,745
  • 1
  • 23
  • 39
  • They said almost asynchronous I/O don't use a thread (https://stackoverflow.com/a/37419845/836376). Do you know any API in .NET Framework like that? – KevinBui Mar 18 '18 at 08:47