【问题标题】:How do I access HttpContext.Current in Task.Factory.StartNew?如何访问 Task.Factory.StartNew 中的 HttpContext.Current?
【发布时间】:2012-05-26 14:35:33
【问题描述】:

我想在我的 asp.net 应用程序中访问 HttpContext.Current

Task.Factory.Start(() =>{
    //HttpContext.Current is null here
});

我该如何解决这个错误?

【问题讨论】:

    标签: c# asp.net .net c#-4.0 asp.net-4.0


    【解决方案1】:

    Task.Factory.Start 会启动一个新的Thread,因为HttpContext.Context 是线程本地的,它不会自动复制到新的Thread,所以你需要手动传递:

    var task = Task.Factory.StartNew(
        state =>
            {
                var context = (HttpContext) state;
                //use context
            },
        HttpContext.Current);
    

    【讨论】:

    • 有趣的是,这对我来说确实很奇怪。例如 HttpContext 的 User 属性在进入线程后变为 null,尽管它在 HttpContext.Current 中有值。
    • 是的,值得注意的是,使用对 HttpContext.Current 的引用可能在很多时候都有效,但不建议这样做,而且有时可能会失败。当 http 请求完成时,ASP 运行时可能会清理对象,然后您会发现 context.Items[x] 之类的内容不包含您之前放置的内容。另见stackoverflow.com/questions/8925227/…
    【解决方案2】:

    您可以使用闭包使其在新创建的线程上可用:

    var currentContext = HttpContext.Current;
    
    Task.Factory.Start(() => {
        // currentContext is not null here
    });
    

    但请记住,任务可能会超过 HTTP 请求的生命周期,并且在请求完成后访问 HTTPContext 时可能会导致有趣的结果。

    【讨论】:

    • 我喜欢使用这种方式,而不是传入状态对象并将项目转换为单独的变量......很乱。
    • 有趣的结果是指任务范围内的旧数据吗?
    【解决方案3】:

    正如David 指出的那样,HttpContext.Current 不会一直有效。就我而言,大约 20 次中有 1 次 CurrentContext 将为空。以下面结束。

    string UserName = Context.User.Identity.Name;
    
    System.Threading.Tasks.Task.Factory.StartNew(() =>
    {
        UserName ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-14
      • 2011-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-15
      • 2011-03-25
      • 1970-01-01
      相关资源
      最近更新 更多