A blocked state is a thread state in which the operating system withholds CPU time while the thread waits for an external operation or another thread. File and network access commonly cause blocking because the thread must wait for data outside the CPU and memory. section 1.1
When blocking begins, the thread releases the CPU and becomes ineligible for CPU time. After the awaited condition is satisfied, it leaves the blocked state and becomes eligible to run again. Keeping many threads blocked wastes memory and increases thread-management overhead. section 1.1
Blocking is especially significant when comparing synchronous and asynchronous implementations:
- Task.Run with synchronous file access can occupy thread-pool threads that remain blocked while the hard drive responds. section 5.1
- Asynchronous file access releases the thread while waiting and uses threads again only when the data arrives and processing can continue. section 5.1
- Waiting for another thread can also cause blocking, not only file or network operations. section 1.1
Ten-file processing
A synchronous ten-file implementation starts ten tasks that perform blocking reads, potentially leaving ten thread-pool threads waiting. Replacing the reads with File.ReadAllBytesAsync and awaiting them allows the threads to be reused during I/O; processing resumes when each file's data arrives. section 5.1
Listing 5.5 Reading 10 files asynchronously and processing the data
public void Process10Files()
{
var tasks = new Task[10];
for(int i=0;i<10;++i)
{
var icopy = i;
tasks[i] = Task.Run(async ()=>
{
await File.ReadAllBytesAsync($"{icopy}.txt");
Console.WriteLine("Doing something with the file's content");
});
}
Task.WaitAll(tasks);
}
Shows a C# implementation that combines asynchronous file reads with processing after each read completes. section 5.1
