异步Action过滤器中访问IHttpContextAccessor是否存在线程安全问题?
Great question! Let’s break this down clearly based on what David Fowler and Damian Edwards covered in their NDC London talk, plus how ASP.NET Core’s request context operates under the hood.
First off: this thread safety warning does NOT only apply to controller action methods—it extends to asynchronous action filters (and any other component that runs as part of the request pipeline) too. Here’s why:
The core issue with
IHttpContextAccessorafter async operations comes down to how ASP.NET Core manages request context. By default,HttpContextis tied to the current request viaAsyncLocal<T>, but once an async operation completes (after anawait), the thread handling the continuation might not be bound to the original request’s context anymore. Worse, if the request has already finished processing by the time the async operation completes, theHttpContextcould have been disposed or recycled entirely, leaving you with anullor invalid context when you try to access it viaIHttpContextAccessor.For asynchronous action filters (like those implementing
IAsyncActionFilter), the same risk applies. If you perform an async operation (e.g.,await someApiCall()) and then try to accessIHttpContextAccessor.HttpContextin the continuation, you’re not guaranteed to get the correct, alive context for the current request. The request might have already completed, or the context might have been detached from the thread.
What’s the safe alternative?
Instead of relying on IHttpContextAccessor after async operations, capture the HttpContext before starting the async work, or use the context directly provided by the filter’s execution context. For example:
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // Capture the HttpContext BEFORE any async work var httpContext = context.HttpContext; // Perform async operation await SomeAsyncWork(); // Use the captured httpContext here—this is safe var userId = httpContext.User.FindFirstValue(ClaimTypes.NameIdentifier); await next(); }
Using the context.HttpContext from the filter’s parameters ensures you’re working with the actual context tied to the current request, and capturing it upfront avoids any issues with context detachment during async flows.
内容的提问来源于stack exchange,提问作者Matt Roberts

