我编写了一个在Azure中托管的MVC 3应用程序。我正在使用Session变量在我长时间运行的进程之一的http调用之间存储更新状态信息。然后,这用于更新进度条。价值观可以很快改变。
使用InProc会话提供程序时,这一切都很有效。但是,每当我更改为使用Azure缓存会话提供程序时,会话变量都不会从长时间运行的进程中更新。
我现在正在改变直接使用Cache变量的东西,这似乎到目前为止。
为什么在缓存中使用Session时,以下方法不起作用,但是InProc很好?
例如,我设置可能会在一个控制器ActionResult
中启动一个会话变量Session["OPERATION_PROGRESS"] = 0;
然后我会像
那样处理会话HttpSessionStateBase session = Session;
并将其传递给我的长时间运行过程,如
LongRunningProcess.Go(session);
然后,在LongRunningProcess方法中,它将使用传递的会话对象更新会话变量。
passedSession["OPERATION_PROGRESS"]=10;
webs客户端调用一个进度页面,该页面将会话变量值传递回来更新进度条。
答案 0 :(得分:2)
根据我最近读到的有关会话提供程序的内容,我怀疑发生的情况是,在初始化长时间运行请求的请求完成后,会话提供程序释放其对会话信息的锁定,从而有效地断开连接。来自MSDN:
在请求结束时,如果会话状态值已经存在 修改后,SessionStateModule实例调用 SessionStateStoreProviderBase.SetAndReleaseItemExclusive方法 将更新的值写入会话状态存储。
还有一个对象可以与你交谈(这就是为什么你的长时间运行过程仍然有效),但是没有对该对象的更改被发送到持久层(这就是为什么后续请求不会接收那些变化)。
我在类似情况下所做的是在请求开始时生成请求ID并在azure表中创建一行,并将其作为分区键(但您可以使用任何您喜欢的存储),传递此ID进入长时间运行的过程并将此id返回给客户端。长时间运行的进程只更新表中的这一行。所有后续的进度请求都会在此请求ID中传递,查找它很简单。要阻止表变得太大,请在发现进程完成的请求上删除该行。
如果要使用azure表存储,对此系统的改进是使用刻度中的当前时间作为分区键,将另一个唯一ID用作行键。通过这种方式,可以很容易地找到表中已存在的行,并将其清除掉。