c# - 从另一个线程访问 session 数据

标签 c# asp.net .net

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

最佳答案

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

如果您的线程的生命周期与页面的生命周期相同,并且您需要大量随机访问 HttpSessionState , 那么你应该得到 SynchronizationContext来自使用静态 Current property 创建后台线程的调用.

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

// 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 之后的代码(即 //之后的行会执行其他操作。 ) 应该独立于传递给 Post 的委托(delegate)。如果后面的代码是依赖的,你需要等待调用完成才能继续,那么你可以调用 Send method ;它具有相同的签名,并且会阻塞直到委托(delegate)中的代码被执行。

就是说,如果您只想只读访问这些值,那么最好在调用您的代码之前获取它们,然后在您的代码中访问它们后台线程:

// 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.
    // ...
});

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

您还必须处理 session 超时问题,您甚至不知道 session 是否在您要访问它时存在

关于c# - 从另一个线程访问 session 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13036928/

相关文章:

.net - 集成(Selenium)测试后回滚数据库

c# - 使用 Dapper 删除 List<T>

c# - 如何根据绑定(bind)值更改 WPF 数据网格行的图像

c# - 标签的默认填充

asp.net - 如何在 Entity Framework 中禁用每个查询的查询执行计划缓存?

c# - 为什么在 ASP.NET 应用程序中使用隔离存储?

asp.net - 为什么 REST API get 调用会调用错误的方法?

c# - 无法将 lambda 表达式转换为类型 "...",因为它不是委托(delegate)类型

c# - ExpertPdf 转换错误 : WebKit Navigation timeout in GetPdfBytesFromUrl

.net - NuGet 限制包的最大主要版本