I have a TPL Task that does two things. First, it calls a web service. Second, it inserts some data into a database. I have up to 20 Tasks started at one time doing this sam
If all an application's tasks block, each task will use a thread from the thread pool.
If all tasks regularly await
, the thread pool does not need to use a thread for every task.
When your code await
s an operation that hasn't completed yet, the method's state is saved such that it can be resumed on any other thread.
Idle threadpool threads get released after a while, so the actual thread which hits an await
can be released from the thread pool while the method calling await
is still running.
Putting all this together, an async version of a routine can do the same work with less threads (assuming the workload has enough balance of time awaiting vs spinning the CPU).
This code runs 100 tasks doing a synchronous wait:
var numTasks = 100;
for (int i = 0; i < numTasks; i++)
{
Thread.Sleep(5);
Task.Run(() =>
{
Thread.Sleep(5000);
Interlocked.Decrement(ref numTasks);
});
}
while (numTasks > 0) Thread.Sleep(100);
For the async wait, change it to:
Task.Run(async () =>
{
await Task.Delay(5000);
Interlocked.Decrement(ref numTasks);
});
On my system the async version grows the peak thread count half as much, and takes 20% of the time to do the same 'work'.