Making blocking calls to async
methods transforms the code into a
synchronous operation. Doing so inside an Azure Function can lead to thread pool exhaustion.
Thread pool exhaustion refers to a situation where all available threads in a thread pool are occupied, and new tasks or work items cannot be
scheduled for execution due to the lack of available threads. This can lead to delayed execution and degraded performance.
class RequestParser
{
[FunctionName(nameof(ParseRequest))]
public static async Task<IActionResult> ParseRequest([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req)
{
// This can lead to thread exhaustion
string requestBody = new StreamReader(req.Body).ReadToEndAsync().Result;
// do stuff...
}
}
Instead, asynchronous mechanisms should be used:
class RequestParser
{
[FunctionName(nameof(ParseRequest))]
public static async Task<IActionResult> ParseRequest([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req)
{
// Non-blocking, asynchronous operation
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
// do stuff...
}
}
This applies to multiple methods that are available when working with tasks:
Goal |
Blocking |
Asynchronous |
Wait for the result of a task |
Task.Wait , Task.Result or Task.GetAwaiter.GetResult
|
await
|
Wait for any of many task to complete |
Task.WaitAny
|
await Task.WhenAny
|
Wait for all of many tasks to complete |
Task.WaitAll
|
await Task.WhenAll
|
Wait a period of time |
Thread.Sleep
|
await Task.Delay
|