在ASP.NET后台线程上使用ThreadStatic数据并设置Thread.CurrentPrincipal.Identity是否安全?

时间:2016-01-15 00:26:52

标签: c# asp.net

正如很好地讨论herehere,您应该使用HttpContext.Current.Items而不是ThreadStatic变量来存储ASP.NET请求的数据,因为您的请求可能是由多个线程处理。

如果你想在后台线程上做某事怎么样?使用ThreadStatic数据并设置Thread.CurrentPrincipal.Identity以避免必须通过所有方法推送“全局”数据是否安全?我假设它很好,但我想确定。例如,我没有在后台线程上执行的代码中明确使用任何await,但我调用的库可能是;可能ASP.NET使用我的线程做其他事情,而这样的同步代码不活动?如果是这样的话,在运行它之前在线程上设置一些“线程静态”数据和用户信息的安全方法是什么?

我很清楚ASP.NET中后台线程上运行代码的the pitfalls。但有时你必须做你必须做的事情。在我的情况下,我们尚未使用.NET 4.5.2,因此无法使用QueueBackgroundWorkItem,因此我们使用Nito.AspNetBackgroundTasks来运行后台任务。这在内部使用Task.Run()

例如,我会做这样的事情:

public class SomeController
{    
    public void AControllerMethod()
    {
        // Get the data set earlier on the HttpContext
        var theData = HttpContext.Current.Items["importantKey"];
        var thePrincipal = HttpContext.Current.User;
        // Pass it to the background thread method
        BackgroundTaskManager.Run(() => DoStuffInBackground(theData, thePrincipal));        
    }

    private void DoStuffInBackground(string someData, IPrincipal user)
    {
        // Store the data & principal for use by logic classes later
        Thread.CurrentPrincipal = user;
        MyContextService.BackgroundData["importantKey"] = someData;

        // do some things, some of which would call:
        aLogicClass.DoSomethingDeepInLogicCode();
    }    
}

public class ExampleLogicClass
{    
    private void DoSomethingDeepInLogicCode()
    {
        // get the context info
        var user = Thread.CurrentPrincipal;
        var theData = MyContextService.GetContextData("importantKey");

        // .. do stuff with user & data....        
    }    
}

public static class MyContextService
{     
    [ThreadStatic]
    public static ConcurrentDictionary<string,object> BackgroundData = new ConcurrentDictionary<string,object>();

    // Gets data from HttpContext or from BackgroundData 
    public object GetContextData(string key)
    {
        if (HttpContext.Current != null)
        { 
            var data = HttpContext.Current.Items[key]; 
            if (data != null) return data;
        } 
        if (BackgroundData.ContainsKey(key))
        {
            return BackgroundData[key];
        }
        return null;
    }    
} 

更新

bit more reading我想我应该使用CallContext.LogicalSetData()和LogicalGetData()来设置/获取ThreadLocal / ThreadStatic数据的等价物。 (或。{4.6}中的AsyncLocal<T>

正确认识这些东西的人会有更多的澄清。

0 个答案:

没有答案