代码之家  ›  专栏  ›  技术社区  ›  Steve

HttpContext异步在中是否安全asp.net核心?

  •  1
  • Steve  · 技术社区  · 6 年前

    根据我读到的 asp.net core 已删除同步上下文。这意味着执行代码的线程 await 等待

    是的 HttpContext async 方法?或者有没有可能在 打电话?

    例如在控制器动作中

    public async Task<IActionResult> Index()
    {
        var context1 = HttpContext;
        await Task.Delay(1000);
        var context2 = HttpContext;
        ....
    }
    

    IHttpContextAccessor

    IHttpContextAccessor.HttpContext 安全的 异步 模式?

    public async void Foo(IHttpContextAccessor accessor)
    {
        var context1 = accessor.HttpContext;
        await Task.Delay(1000);
        var context2 = accessor.HttpContext;
    }
    
    0 回复  |  直到 6 年前
        1
  •  5
  •   Stephen Cleary    6 年前

    那么HttpContext在异步方法中使用仍然安全吗?或者有没有可能在等待呼叫后得到不同的上下文?

    整个问题 async HttpContext 以及ASP.NETpre-Core是因为代码通常 HttpContext.Current . ASP.NET是一个多线程服务器 await AspNetSynchronizationContext 有管理的环境 在异步代码恢复之前。

    没有 同步上下文。但没关系,因为 HttpContext.Current 请求上下文 实例通过本地属性(例如。, 请求上下文 IHttpContextAccessor ).

    (学究注:上面的解释有点简化了-ASP.NET核心前同步上下文处理了除此之外的其他事情 HttpContext.Current

    所以,上下文不可能不同。它们是相同的属性-相同的对象实例。问题在于ASP.NET前核心是 值属性 HttpContext.Current ,已在中删除ASP.NET核心。

        2
  •  1
  •   0lukasz0    5 年前

    根据文件: https://docs.microsoft.com/en-en/aspnet/core/performance/performance-best-practices?view=aspnetcore-3.1#do-not-capture-the-httpcontext-in-background-threads

    并行线程会导致未定义的行为,例如挂起, 崩溃和数据损坏。

    并在传出HTTP之前和之后记录传入请求路径

    public class AsyncBadSearchController : Controller
    {       
        [HttpGet("/search")]
        public async Task<SearchResults> Get(string query)
        {
           var query1 = SearchAsync(SearchEngine.Google, query);
           var query2 = SearchAsync(SearchEngine.Bing, query);
           var query3 = SearchAsync(SearchEngine.DuckDuckGo, query);
    
           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)
        {
            var searchResults = _searchService.Empty();
            try
            {
                _logger.LogInformation("Starting search query from {path}.", 
                                        HttpContext.Request.Path);
                searchResults = _searchService.Search(engine, query);
                _logger.LogInformation("Finishing search query from {path}.", 
                                        HttpContext.Request.Path);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed query from {path}", 
                                 HttpContext.Request.Path);
            }
    
            return await searchResults;
        }
    }
    

    执行以下操作:下面的示例复制传入的所有数据 在发出三个并行请求之前请求。

    public class AsyncGoodSearchController : Controller
    {       
        [HttpGet("/search")]
        public async Task<SearchResults> Get(string query)
        {
            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 = _searchService.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 await searchResults;
        }
    }
    
    推荐文章