Task.Run内部的ASP.NET HttpContext.Current [英] ASP.NET HttpContext.Current inside Task.Run

查看:342
本文介绍了Task.Run内部的ASP.NET HttpContext.Current的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个下面的代码示例,该示例在ASP.NET MVC应用程序中使用. 这段代码的目的是创建即发即弃"请求,以便对一些长时间运行的操作进行排队.

I have a following code example that is used in ASP.NET MVC application. The purpose of this code is to create "fire and forget" request for queuing some long running operation.

public JsonResult SomeAction() {
   HttpContext ctx = HttpContext.Current;            

   Task.Run(() => {
       HttpContext.Current = ctx;
       //Other long running code here.
   });

   return Json("{ 'status': 'Work Queued' }");
}

我知道这不是在异步代码中处理HttpContext.Current的好方法,但是当前我们的实现不允许我们做其他事情. 我想了解这段代码有多危险...

I know this is not a good way for handling HttpContext.Current in asynchronous code, but currently our implementation not allows us to do something else. I would like to understand how much this code is dangerous...

问题:从理论上讲,是否可以在Task.Run中设置HttpContext,将上下文完全设置为另一个请求?

The question: Is it theoretically possible that setting the HttpContext inside Task.Run, will set the context to totally another request?

我认为是,但是我不确定.我的理解: Request1由线程池中的Thread1处理,然后在Thread1绝对处理另一个请求(Request2)时,Task.Run中的代码会将上下文从Request1设置为Request2.

I think yes, but I'm not sure. How I understand it: Request1 is handled with Thread1 from thread pool, then while Thread1 is handling absolutelly another request (Request2), the code inside Task.Run will set context from Request1 to Request2.

也许我错了,但是我对ASP.NET内部的了解使我无法正确理解它.

Maybe I am wrong, but my knowledge of ASP.NET internals not allows me to understand it correctly.

谢谢!

推荐答案

让我向您介绍一些内部问题:

Let me bump a little internals on you:

public static HttpContext Current
{
    get { return ContextBase.Current as HttpContext; }
    set { ContextBase.Current = value; }
}

internal class ContextBase
{
    internal static object Current
    {
        get { return CallContext.HostContext; }
        set { CallContext.HostContext = value; }
    }
}

public static object HostContext
{
    get 
    {
        var executionContextReader = Thread.CurrentThread.GetExecutionContextReader();
        object hostContext = executionContextReader.IllogicalCallContext.HostContext;
        if (hostContext == null)
        {
            hostContext = executionContextReader.LogicalCallContext.HostContext;
        }
        return hostContext;
   }
   set
   {
        var mutableExecutionContext = Thread.CurrentThread.GetMutableExecutionContext();
        if (value is ILogicalThreadAffinative)
        {
            mutableExecutionContext.IllogicalCallContext.HostContext = null;
            mutableExecutionContext.LogicalCallContext.HostContext = value;
            return;
        }
        mutableExecutionContext.IllogicalCallContext.HostContext = value;
        mutableExecutionContext.LogicalCallContext.HostContext = null;
   }
}

所以

var context = HttpContext.Current;

等于(伪代码)

var context = CurrentThread.HttpContext;

并在您的Task.Run内部发生这种情况

and inside your Task.Run something like this happens

CurrentThread.HttpContext= context;

Task.Run将使用线程池中的线程启动新任务.因此,您要说的是,新线程"HttpContext属性"是对启动线程"HttpContext属性"的引用-到目前为止(与启动线程完成后将要面对的所有NullReference/Dispose异常一样).问题是,如果在您的

Task.Run will start new task with thread from thread pool. So you're telling that your new thread "HttpContext property" is reference to starter thread "HttpContext property" - so far so good (well with all the NullReference/Dispose exceptions you'll be facing after your starter thread finishes). Problem is if inside your

//Other long running code here.

您有类似的声明

var foo = await Bar();

一旦您点击等待,您当前的线程将返回到线程池,并且在IO完成之后,您将从线程池中获取新线程-想知道它的"HttpContext属性"是什么,对吧?我不知道:)最有可能您会以NullReferenceException结尾.

Once you hit await, your current thread is returned to thread pool, and after IO finishes you grab new thread from thread pool - wonder what its "HttpContext property" is, right ? I don't know :) Most probably you'll end with NullReferenceException.

这篇关于Task.Run内部的ASP.NET HttpContext.Current的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆