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

Keep session alive for long running process with jQuery

本文关键字:会话 活动 过程 jQuery 长时间 运行 使用      更新时间:2023-09-26

我有一个父窗体,它在IFrame中包含另一个内容页。当用户单击内容页中的链接时,将启动一个长时间运行的过程(> 30分钟)。完成后,将向用户显示一个弹出窗口,指示已处理的记录数。

我需要以编程方式防止会话超时,而不改变Web.config中的默认20分钟。我一直在尝试实现心跳的例子张贴在这里(和所有的网络,所以我知道它应该工作)让ASP。. NET会话打开/激活

在我的例子中,一旦内容页请求转到服务器端并且启动了长时间运行的流程,就不会调用HTTP Handler。当进程完成后,所有的调用都立即一个接一个地进行,就像它们已经"排队"一样。

这是我的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文件中声明,该文件包含在应用程序的所有页面中。

这是我在内容页的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在单个线程中运行,但考虑到我的重复间隔在内容页之外的事实,我不认为这应该适用于这里…

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

从这篇MSDN文章…

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

请参阅此页,了解有关该问题的更详细解释,以及使您更好地控制如何实现阻塞的解决方案和潜在的解决方案。

我想你这里有几个移动的部分互相阻碍,无法正常工作。

  • 因为你的进程在服务器线程中运行,这会阻止其他请求被处理。
  • 因为keepalive依赖于从服务器获得响应,所以它没有完成。

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