Question:
I am reading this article about using Task and async-await in C# It contains the following code
var client = new WebClient();
var task = client.DownloadStringTaskAsync("/api/blabla");
Console.WriteLine("Hello world!");
var result = await task;
Console.WriteLine("Got some data");
and then this is what is said about him
Why is this code good and correct? Because DownloadStringTaskAsync returns a Task that encapsulates an I/O operation – that is, an I/O bound operation. And almost all I / O is asynchronous – that is, for its implementation, nowhere, starting from the highest level of calling the DownloadStringTaskAsync method and ending with the network card driver, absolutely nowhere is an additional thread needed to "wait" or "process" this operation .
Similarly, an example from JS/jQuery is given
$.get('/api/blabla', function(data) {
console.log("Got some data.");
});
console.log("Hello world!")
and a comment on it
This is a very clear example of asynchronous programming. There is no multi-threading here – Javascript is strictly single-threaded
In both cases, it is especially noted that there is no multithreading here. And I also read similar things in other sources that using async-await (and asynchrony in general) does not always imply the use of an additional thread. And this is completely incomprehensible to me. Let's take the same jQuery example. First, the request is executed, which has a callback, and then the message "Hello world!" Is displayed. But since the request is executed asynchronously, "Hello world!" output earlier. And it's not clear to me how to do without multiple threads? After all, if an asynchronous request is executed in the same thread as the main one, then in theory there should not be asynchrony either, because the thread must first wait for the request to complete and only then display "Hello world!". The same goes for C# code. Please explain why the author so stubbornly says that there is no multithreading here? Thanks in advance!
Answer:
The fact is that network and disk calls in Windows support the so-called Overlapped I / O , which allows you to receive a notification when the operation is completed. Those. while performing a disk or network operation, the user thread can do whatever it wants, and not necessarily sleep and wait for the results.
How normal, non-asynchronous reading works:
- Your code is making a synchronous call
- The thread that made the call goes to sleep
- Data is read from disk or network
- The flow is waking up
- The call returns a result
How asynchronous reading works
- Your code is making an asynchronous call
- The thread that made the call is freed – returned to the pool
- Data is read from disk or network
- The application receives notification from the system that data has been received (via the I/O Completion Port)
- The runtime finds the code that should process the result – the continuation of your async method and puts it to execution.
- Your code returns a result
The difference is that between 2 and 6 in asynchronous code no thread sleeps waiting for the result. And threads in Win are quite a valuable resource. They are hard (relatively hard) to run. They require memory (about 1Mb per thread). They need to be synchronized – the more threads, the more overhead.
In addition, if there is something in your code that can be executed between 2 and 6 (for example, you did not immediately require the result of reading from disk or from the network), then this will be executed by the thread, instead of an empty wait. In this case, there will be simultaneous execution of your code, and physical reading of data from the network.
But there will still be no multithreading – then you will have exactly one thread. The fact that the network card driver reads the data does not add another thread to your application. And you can safely do without synchronization, and other troubles associated with multithreading.
Abstraction, as without it:
- multi-threaded pizza making – clone yourself and make the clone cook pizza. at the end – merge into one person.
- asynchronous pizza making – call the delivery, calmly do your business, open the doorbell and pick up the finished pizza.