从另一个线程访问会话数据

时间:2012-10-23 18:33:04

标签: c# asp.net .net

我在这里有一个问题。在我的网络应用程序中,我有一个页面,启动另一个线程,耗时的任务。在这个新线程中,我调用了一个我的架构方法(在另一个项目中 - 一个架构项目)。问题是:在其中一种方法中,我访问 HttpContext.Current.Session 字段。但是,当我启动应用程序时,会抛出一个异常,说该对象( HttpContext.Current.Session )具有空引用。我如何设置新线程的上下文与HttpApplication上下文相同才能访问 HttpContext.Current.Session

2 个答案:

答案 0 :(得分:8)

这里有很多事情需要考虑。

如果您的线程的生命周期与页面的生命周期相等,并且您需要对HttpSessionState进行大量随机访问,那么您应该从创建后台线程的调用中获取SynchronizationContext使用静态Current property

一旦你有了,你可以将它传递给你的线程,然后当你需要访问与请求相关的HttpContextBase上的任何时(这包括会话),你可以调用您传递给线程的SynchronizationContext上的Post method来获取值(或设置它们):

// From thread servicing request.
var sc = SynchronizationContext.Current;

// Run the task
Task t = Task.Run(() => {
    // Do other stuff.
    // ...

    // The value to get from the session.
    string sessionValue = null;

    // Need to get something from the session?
    sc.Post(() => {
        // Get the value.
        sessionValue = HttpContext.Current.Session["sessionValue"];
    }

    // Do other stuff.
    // ...
});

执行此操作非常重要,因为对HttpContextBase(以及与之关联的任何内容)的访问是线程安全的,并且与线程(井,上下文)处理相关联请求。

请注意,Post方法不会阻塞,因此调用Post之后的代码(即// Do other stuff.之后的行)应该独立于传递给的Post代理。 // Get the values needed in the background thread here. var values = { SessionValue = HttpContext.Current.Session["sessionValue"]; }; // Run the task Task t = Task.Run(() => { // Do other stuff. // ... // Work with the session value. if (values.SessionValue == ...) // Do other stuff. // ... }); 。如果之后的代码是依赖的,您需要等待呼叫完成才能继续,那么您可以调用Send method;它具有相同的签名,并将阻塞,直到代理中的代码被执行。

也就是说,如果您只想只读访问这些值,那么最好在调用代码之前让它们,然后在您的代码中访问它们后台主题​​:

{{1}}

如果您的线程将在请求服务后继续处理,那么具有只读状态,并且 在您启动之前捕获它线程。一旦请求得到服务,即使会话存在,这也是一个合乎逻辑的概念;根据会话状态的提供者(会话状态管理器,SQL Server等),每次有新请求进入时,对象都可以被水合。

您还必须处理会话超时问题,在您想要访问它时,您不会知道会话是否存在

答案 1 :(得分:1)

您无法在线程中访问会话,但可以使用以下方式共享您的数据:HttpRuntime.Cache

但要注意以下几点:与会话不同,缓存会过期。此外,缓存在所有Web用户之间共享。