Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 会话在不同线程中变为空_Asp.net Mvc_Session - Fatal编程技术网

Asp.net mvc 会话在不同线程中变为空

Asp.net mvc 会话在不同线程中变为空,asp.net-mvc,session,Asp.net Mvc,Session,我有一个在不同线程中运行的任务,需要该会话。我已经做到了: public GenerateDocList(LLStatistics.DocLists.DocList docs) { this.docs = docs; context = HttpContext.Current; } 及 现在线程已经知道了会话,它工作了一段时间,但在我的循环HttpContext.Current.session中的某个点变为nul

我有一个在不同线程中运行的任务,需要该会话。我已经做到了:

public GenerateDocList(LLStatistics.DocLists.DocList docs)
        {
            this.docs = docs;

            context = HttpContext.Current;
        }

现在线程已经知道了会话,它工作了一段时间,但在我的循环
HttpContext.Current.session
中的某个点变为null。你知道我能做些什么吗

public static LLDAC.DAL.DBCTX LLDB
        {
            get
            {
                LLDAC.DAL.DBCTX currentUserDBContext = HttpContext.Current.Session["LLDBContext"] as LLDAC.DAL.DBCTX;
                if (currentUserDBContext == null)
                {
                    currentUserDBContext = new LLDAC.DAL.DBCTX();
                   HttpContext.Current.Session.Add("LLDBContext", currentUserDBContext);//this works only for a few loop iterations
                }
                return currentUserDBContext;
            }
        }

通常,对于多线程操作来说,这是一种非常脆弱的模式。长时间运行的任务(我假设是这样)最适合于类中的实例方法,而不是静态方法,这样类就可以维护任何依赖对象。此外,由于会话状态不是线程安全的,并且可以跨越多个请求,因此,通过在会话中兑现您的DB上下文,您将陷入一些非常危险的业务中

如果您确信最好使用静态方法并将其存储在会话中,则可以执行以下操作:

public static HttpSessionState MySession { get; set; }

public GenerateDocList(LLStatistics.DocLists.DocList docs)
{
    this.docs = docs;

    MySession = HttpContext.Current.Session;
}
public class DocListGenerator : IDisposable
{
    public LLDAC.DAL.DBCTX LLDB { get; private set; }
    public DocListGenerator()
    {
        LLDB = new LLDAC.DAL.DBCTX();
    }

    public void GenerateList()
    {
        // Put loop here.
    }

    public void Dispose()
    {
        if (LLDB != null)
        {
            LLDB.Dispose();
        }
    }
}
public void StartTask()
{
    using (DocListGenerator generator = new DocListGenerator()
    {
        generator.GenerateList();
    }
}
HttpContext.Current.Sesssion.Add("ListGenerator", generator);
然后:

请注意,由于其他线程仍然可以修改会话,因此会话仍然可能会遇到问题

更好的解决方案可能如下所示:

public static HttpSessionState MySession { get; set; }

public GenerateDocList(LLStatistics.DocLists.DocList docs)
{
    this.docs = docs;

    MySession = HttpContext.Current.Session;
}
public class DocListGenerator : IDisposable
{
    public LLDAC.DAL.DBCTX LLDB { get; private set; }
    public DocListGenerator()
    {
        LLDB = new LLDAC.DAL.DBCTX();
    }

    public void GenerateList()
    {
        // Put loop here.
    }

    public void Dispose()
    {
        if (LLDB != null)
        {
            LLDB.Dispose();
        }
    }
}
public void StartTask()
{
    using (DocListGenerator generator = new DocListGenerator()
    {
        generator.GenerateList();
    }
}
HttpContext.Current.Sesssion.Add("ListGenerator", generator);
那么您的呼叫代码如下所示:

public static HttpSessionState MySession { get; set; }

public GenerateDocList(LLStatistics.DocLists.DocList docs)
{
    this.docs = docs;

    MySession = HttpContext.Current.Session;
}
public class DocListGenerator : IDisposable
{
    public LLDAC.DAL.DBCTX LLDB { get; private set; }
    public DocListGenerator()
    {
        LLDB = new LLDAC.DAL.DBCTX();
    }

    public void GenerateList()
    {
        // Put loop here.
    }

    public void Dispose()
    {
        if (LLDB != null)
        {
            LLDB.Dispose();
        }
    }
}
public void StartTask()
{
    using (DocListGenerator generator = new DocListGenerator()
    {
        generator.GenerateList();
    }
}
HttpContext.Current.Sesssion.Add("ListGenerator", generator);
如果确实要缓存某些内容,可以像下面这样缓存实例:

public static HttpSessionState MySession { get; set; }

public GenerateDocList(LLStatistics.DocLists.DocList docs)
{
    this.docs = docs;

    MySession = HttpContext.Current.Session;
}
public class DocListGenerator : IDisposable
{
    public LLDAC.DAL.DBCTX LLDB { get; private set; }
    public DocListGenerator()
    {
        LLDB = new LLDAC.DAL.DBCTX();
    }

    public void GenerateList()
    {
        // Put loop here.
    }

    public void Dispose()
    {
        if (LLDB != null)
        {
            LLDB.Dispose();
        }
    }
}
public void StartTask()
{
    using (DocListGenerator generator = new DocListGenerator()
    {
        generator.GenerateList();
    }
}
HttpContext.Current.Sesssion.Add("ListGenerator", generator);

但是,我仍然不认为这是一个特别好的主意,因为您的上下文仍然可以由不同的线程处理或以其他方式更改。

使用与HttpContext相关的任何内容。在ASP.net中,除主请求线程外的任何内容上的当前内容通常都会给您带来麻烦

HttpContext实际上是在属于线程池的线程上进行备份的,该线程很可能在另一个请求上被重用

在ASP.net中使用新的Async/Await关键字实际上也是一个常见问题

为了帮助你,首先知道你为什么要这样做会有帮助吗

  • 这是一台服务器还是一个具有多个负载平衡服务器的web场
  • 您是自己托管,还是由提供商托管
  • SessionState实现是什么(SQL Server、状态服务器、进程中或诸如MemCached、Redis等自定义内容)
  • 什么版本的ASP.net
  • 为什么要启动一个新线程,而不仅仅是在请求线程上进行处理

  • 如果您确实不能(或不应该)使用会话。然后你可以使用相关ID之类的东西

    Guid correlationID=Guid.NewGuid()

    HttpContext.Current.Session[“DocListID”]=correlationID

    Gooffand GenerateSomestuffonanewThread(correlationID)

    。。。处理完成后,使用指定的ID将结果存储在某处

    //将结果序列化到SQL server、文件系统、缓存。。。 DocList.StoreResultsSomewhereUnderID()

    。。。后来


    DocList.CheckForResultsUnderID(HttpContext.Current.Session[“DocListID”])

    你所说的“暂时有效”是什么意思?它能工作吗?比如说15分钟后它返回null?当您在HttpContext中传递给新线程时,您正在从主线程传递对原始对象的引用。这里的问题是,主线程很可能已经解决,HttpContext已经被GC删除。HttpContext对象不是为在主线程之外访问而设计的,并且不是线程安全的。因此,我不建议在其他线程中访问它。您为什么不为新线程创建DB上下文的新实例,而不尝试将其存储在会话中?