HttpContext is not thread-safe. Accessing it from multiple threads in parallel can cause corruption, hangs, crashes, or data corruption. If you need to use data from the HttpContext (like Request.Path) inside parallel tasks or background operations, copy the required data into local variables before starting the parallel work.
public class AsyncController : Controller
{
[HttpGet("/search")]
public async Task<SearchResults> Get(string query)
{
// Copy data from HttpContext before starting parallel tasks
string path = HttpContext.Request.Path;
var query1 = SearchAsync(SearchEngine.Google, query, path);
var query2 = SearchAsync(SearchEngine.Bing, query, path);
var query3 = SearchAsync(SearchEngine.DuckDuckGo, query, path);
await Task.WhenAll(query1, query2, query3);
var results1 = await query1;
var results2 = await query2;
var results3 = await query3;
return SearchResults.Combine(results1, results2, results3);
}
private async Task<SearchResults> SearchAsync(SearchEngine engine, string query, string path)
{
var searchResults = SearchResults.Empty;
try
{
_logger.LogInformation("Starting search query from {path}.", path);
searchResults = await _searchService.SearchAsync(engine, query);
_logger.LogInformation("Finishing search query from {path}.", path);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed query from {path}", path);
}
return searchResults;
}
}