我开发了一个基于 ASP.NET 的电子商务系统和一个ERP系统,Microsoft Dynamics AX 4.0。
对于每个HTTP会话,我使用“业务连接器”(.NET组件)登录ERP系统。 “业务连接器”对象存储在会话变量中。因此,在正常的 Session_end 中,我将从Dynamics AX注销并清理所有资源
ERP系统是一个基于32位的系统,为了节省资源,我想开发一个在一段时间不活动后退出ERP系统的计时器。让我们说2分钟。 Http会话超时设置为20分钟。
我创建了一个使用System.Timers.Timer
的“TimerHandler”类,每当用户点击与ERP系统相关的内容(项目,购物篮等)时,它就会启动并重新启动计时器。
示例代码:
public class ErpHandler
{
private ErpTimerHandler TimerHandler
{
get
{
if (HttpContext.Current != null)
{
if (HttpContext.Current.Session["TimerHandler"] != null)
{
return (ErpTimerHandler)HttpContext.Current.Session["TimerHandler"];
}
}
return null;
}
set
{
if (HttpContext.Current != null)
{
HttpContext.Current.Session["TimerHandler"] = value;
}
}
}
private void StartTimer()
{
ErpTimerHandler timer = TimerHandler;
if timer == null)
{
timer = TimerHandler.Instance();
timer.TimerEvent += OnTimedEvent;
TimerHandler = timer;
}
timer.StartTimer();
}
private void StopTimer()
{
ErpTimerHandler timer = TimerHandler;
if (timer != null)
{
timer.StopTimer();
TimerHandler = null;
}
}
private void OnTimedEvent(Object source, EventArgs e)
{
StopTimer();
ErpLogOff();
}
public void ErpLogOff()
{
ErpSystem erp = ErpInstance;
if (LoggedOnErp && erp != null)
{
erp.Logoff();
ErpInstance = null;
}
LoggedOnErp = false;
}
}
此代码永远不会在OnTimedEvent
上注销Erp,因为HttpContext.Current.Session
为空。
根据我的理解,计时器在不同的线程上运行,因此当我需要它时,当前会话不可用。
那么我怎么能“达到”那个线程呢?或者我可以确保计时器与会话在同一个线程上运行吗?
答案 0 :(得分:1)
HttpContext.Current
仅在请求生命周期内有效。当您的计时器触发请求时,可能已经处理完毕。
如果您想为特定用户处理某些数据,您应该将会话字典中的信息复制到某种数据持有者中。
这是一个使用内置缓存来检测会话何时到期的解决方案:http://www.ivan-nikolov.com/en/article/5/asp-net-session-state-mode-and-session-end-callback
解决方案基本上在用户登录时将项目插入缓存中,然后在每个请求上更新缓存。最后,它使用缓存过期事件来检测会话何时到期。