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关键字实际上也是一个常见问题 为了帮助你,首先知道你为什么要这样做会有帮助吗
如果您确实不能(或不应该)使用会话。然后你可以使用相关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上下文的新实例,而不尝试将其存储在会话中?