2

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

4

2 回答 2

2

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

从这篇MSDN 文章...

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

有关问题的更详细说明和解决方法,请参阅此页面,该解决方法可让您更好地控制阻止的实施方式和潜在的解决方法。

于 2013-03-25T16:24:05.477 回答
0

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

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

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

于 2013-03-25T17:45:44.303 回答