2013-03-25 56 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

相關問題