2013-03-25 57 views
2

在ASP.NET Web窗体应用程序中,我有一个父窗体,其中包含IFrame中的另一个内容页面。当用户点击内容页面中的链接时,会启动长时间运行的流程(> 30分钟)。完成后,向用户显示一个弹出窗口,指出已处理记录的数量。使用jQuery将会话保持长时间运行状态

我需要以编程方式防止会话超时,而不更改Web.config中的默认20分钟。 我一直在试图实现这里发布的心跳示例(以及遍布网络,所以我知道它应该工作) Keeping ASP.NET Session Open/Alive ,但它似乎主要用于空闲会话。

就我而言,一旦内容页面请求进入服务器端并启动长时间运行的进程,就不会调用HTTP处理程序。当这个过程完成后,所有的呼叫都会立即一个接一个地进行,就像他们已经“排队”一样。

这里是我的HTTP处理程序:

<%@ WebHandler Language="VB" Class="KeepSessionAliveHandler" %> 

Imports System 
Imports System.Web 

Public Class KeepSessionAliveHandler 
    Implements IHttpHandler, SessionState.IRequiresSessionState 

    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest 
     context.Session("heartbeat") = DateTime.Now 
     context.Response.AddHeader("Content-Length", "0") 

    End Sub 

    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable 
     Get 
      Return False 
     End Get 
    End Property 

End Class 

JavaScript函数在头元素父页面。创建间隔每8秒调用一次处理程序(在生产中增加到10分钟)。

function KeepSessionAlive() 
{  
    if (intervalKeepAliveID) 
     clearTimeout(intervalKeepAliveID); 

    intervalKeepAliveID = setInterval(function() 
    { 
     $.post("KeepSessionAliveHandler.ashx", null, function() 
     { 
      // Empty function 
     }); 
    }, 8000); 
} 

intervalKeepAliveID被包含在应用程序的所有页面中主要的Javascript文件中声明。

这是在内容页头

$(document).ready(function() 
{ 
    // Ensuring my code is executed before ASP.NET generated script 
    $("#oGroup_lnkSubmit_lnkButton").attr("onclick", null).removeAttr("onclick").click(function() 
    { 
     // Prevent the browser from running away 
     // e.preventDefault(); 

     window.parent.KeepSessionAlive();    

     // Wave goodbye 
     //window.location.href = $(this).attr('href'); 

     WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions($(this).attr("name"), "", true, "", "", false, false));      
    }); 
}); 

某处,我读了的Javascript在单个线程上运行我的onclick事件的代码,但鉴于这一事实,我的重复间隔是内容页外,我不相信这应该在这里...

+0

你用什么来回应用户? (您的页面是否轮询完成?或者您是否使用服务器端信令框架?)并且,长时间运行的进程是否直接在您的服务器线程中运行?或者你启动一个工作线程? – GalacticCowboy 2013-03-25 16:19:01

+1

阻止访问会话的请求被阻止,而另一个请求可能具有对会话的写访问权限。这是为了防止cropss-threading问题。我在其他地方给出了答案的细节,我会看看我是否可以挖掘它 – Basic 2013-03-25 16:21:28

+0

没有工作线程,它是onclick事件背后的代码的一部分(它实际上是一个使用链接的用户控件)。我可以看到我的代码在Firebug调试器中被击中。该页面不会轮询完成。这是非常标准的网页形式 - “点击做长时间运行的过程,并返回;也显示弹出” – ChicagoMyKindOfTown 2013-03-25 16:28:17

回答

2

这不是一个问题,JS是单线程 - AJAX的A代表异步 - 例如它不会阻止(即使你告诉它阻止,它是真的只是保持状态直到收到响应)

从这个MSDN article ...

访问ASP.NET会话状态是每个会话,这意味着如果两个不同的用户进行的并发请求,访问每个单独的会话同时授予独占。但是,如果为同一会话创建两个并发请求(通过使用相同的SessionID值),则第一个请求将获得对会话信息的独占访问权限。第二个请求仅在第一个请求完成后执行。 (如果由于第一个请求超出锁定超时而释放对信息的排他锁,则第二个会话也可以访问。)如果@ Page指令中的EnableSessionState值设置为ReadOnly,则只读请求会话信息不会导致对会话数据的独占锁定。但是,会话数据的只读请求可能仍然需要等待由会话数据的读写请求设置的锁定清除。

See this page有关该问题的更详细说明和解决方法,使您可以更好地控制如何实施阻止以及潜在的解决方法。

+0

正确!感谢您抽出时间了解我的长期问题和您的迅速回应。 – ChicagoMyKindOfTown 2013-03-25 17:54:01

+0

@ChicagoMyKindOfTown非常欢迎 - 我认识到这个问题,因为我以前自己打过。欢迎来到SO。希望将来我们会看到你。 – Basic 2013-03-25 19:00:45

0

我想你在这里有几个移动的部件阻止对方的行为正确。

  • 由于您的进程正在服务器线程中运行,因此会阻止处理其他请求。
  • 由于Keepalive取决于从服务器获取响应,因此无法完成。

我建议你寻找到一个解决方案一样ASP.NET SignalR,与产卵长期运行过程作为一个单独的线程一起,使您的服务器能够继续服务传入的请求。

+0

感谢您花时间了解我的长问题并提供答案! – ChicagoMyKindOfTown 2013-03-25 18:00:23

相关问题