我有一个在不同线程中运行的任务,需要会话。我已经完成了:
public GenerateDocList(LLStatistics.DocLists.DocList docs)
{
this.docs = docs;
context = HttpContext.Current;
}
和
public void StartTask()
{
//this code runs in a separate thread
HttpContext.Current = context;
/* rest of the code */
}
现在线程知道会话并且它有效一段时间但是在我的循环HttpContext.Current.Session
中的某个时刻变为空。我有什么想法可以做些什么吗?
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;
}
}
答案 0 :(得分:0)
通常,这对于多线程操作来说是一个非常脆弱的模式。长时间运行的任务(我假设这是)最适合类中的实例方法而不是静态方法,以便类可以维护任何依赖对象。此外,由于会话状态不是线程安全的,并且可以跨越多个请求,您将通过在会话中兑现您的数据库上下文来进入一些非常危险的业务。
如果您确信最好使用静态方法并将其存储在会话中,您可以执行以下操作:
public static HttpSessionState MySession { get; set; }
public GenerateDocList(LLStatistics.DocLists.DocList docs)
{
this.docs = docs;
MySession = HttpContext.Current.Session;
}
然后:
public static LLDAC.DAL.DBCTX LLDB
{
get
{
LLDAC.DAL.DBCTX currentUserDBContext = MySession["LLDBContext"] as LLDAC.DAL.DBCTX;
if (currentUserDBContext == null)
{
currentUserDBContext = new LLDAC.DAL.DBCTX();
if (MySession == null)
{
thow new InvalidOperaionException("MySession is null");
}
MySession.Add("LLDBContext", currentUserDBContext);
}
return currentUserDBContext;
}
}
请注意,您仍然可能遇到会话问题,因为其他线程仍然可以修改会话。
更好的解决方案可能看起来像这样:
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);
但是,我仍然不认为这是一个特别好的主意,因为你的上下文仍然可以通过不同的线程处理或以其他方式改变。
答案 1 :(得分:0)
在主要的Request线程之外的任何地方使用与HttpContext.Current相关的任何东西通常会让你在ASP.net中遇到麻烦。
HttpContext实际上是在属于线程池的线程上备份的,并且线程很可能会在另一个请求上重用。
这实际上是在ASP.net中使用新的Async / Await关键字的常见问题。
为了帮助你,首先要知道你为什么要这样做?
如果你真的不能(或不应该)使用会话。然后你可以使用类似相关ID的东西。
Guid correlationID = Guid.NewGuid();
HttpContext.Current.Session [“DocListID”] = correlationID;
DocList.GoOffAndGenerateSomeStuffOnANewThread(的correlationID);
...当进程完成后,使用指定的ID
将结果存储在某处//将结果序列化为SQL服务器,文件系统,缓存... DocList.StoreResultsSomewhereUnderID();
......稍后
DocList.CheckForResultsUnderID(HttpContext.Current.Session [ “DocListID”]);