使用jQuery为长时间运行的进程保持会话活动

时间:2013-03-25 16:16:30

标签: javascript jquery asp.net

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

我需要以编程方式阻止会话超时,而不更改Web.config中的默认20分钟。 我一直在尝试实现这里发布的Heartbeat示例(以及整个网络,所以我知道它应该工作) 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

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

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

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

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

这是我在内容页面Head

中的onclick事件的代码
$(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在单个线程中运行,但鉴于我的重复间隔在内容页面之外,我不相信这应该适用于此...

2 个答案:

答案 0 :(得分:2)

JS是单线程的问题--AJAX代表异步 - 例如它不会阻塞(即使你告诉它阻止它,它实际上只是保留状态直到收到响应)

从此MSDN article ...

  

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

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

答案 1 :(得分:0)

我认为你这里有几个活动部件会阻止对方行为正常。

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

我建议您查看像ASP.NET SignalR这样的解决方案,并将长时间运行的进程作为一个单独的线程生成,以便您的服务器可以继续为传入的请求提供服务。