【问题标题】:Keep session alive for long running process with jQuery使用 jQuery 为长时间运行的进程保持会话活动
【发布时间】:2013-03-15 05:18:09
【问题描述】:

在一个 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 在单线程中运行,但鉴于我的重复间隔在内容页面之外,我认为这不应该适用于此...

【问题讨论】:

  • 你用什么来响应用户? (您的页面是否轮询完成?或者您是否使用服务器端信号框架?)而且,长时间运行的进程是否直接在您的服务器线程中运行?还是你启动一个工作线程?
  • 阻止访问会话的请求,而另一个请求可能对会话具有写访问权限。这是为了防止作物线程问题。我在其他地方的答案中给出了详细信息,我会看看我是否可以挖掘它
  • 没有工作线程,它是 onclick 事件背后代码的一部分(它实际上是一个使用链接的用户控件)。我可以看到我的代码在 Firebug 调试器中被命中。该页面不会轮询完成。这是非常标准的 Web 表单 - “点击执行长时间运行的过程并返回;还显示弹出窗口”

标签: javascript jquery asp.net


【解决方案1】:

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

来自这个MSDN article...

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

See this page 获取更详细的问题说明和解决方法,让您更好地控制阻止的实施方式和潜在的解决方法。

【讨论】:

  • 正确!感谢您抽出宝贵时间了解我的冗长问题并迅速回复。
  • @ChicagoMyKindOfTown 不客气——我意识到了这个问题,因为我以前自己也遇到过。欢迎来到 SO。希望我们将来能见到你。
【解决方案2】:

我认为这里有几个活动部件相互阻碍,无法正常运行。

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

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

【讨论】:

  • 感谢您抽出宝贵时间了解我的长问题并提供答案!
猜你喜欢
  • 1970-01-01
  • 2023-02-13
  • 1970-01-01
  • 2019-06-15
  • 2012-11-26
  • 2011-02-03
  • 1970-01-01
  • 1970-01-01
  • 2013-04-10
相关资源
最近更新 更多