2010-08-25 64 views
2

在ASP.Net中,我想在頁面已經發送給用戶之後運行一些代碼(日誌記錄,其他清理)。我不希望此代碼干擾客戶端接收響應所花費的時間。我試着將這段代碼放在頁面的OnUnload部分,但通過測試(使用斷點或繁忙的等待循環),客戶端實際上不顯示頁面,直到OnUnload中的代碼完成執行。儘管此時響應對象不再可用,因此我會假設緩衝響應已發送到客戶端,但客戶端仍然不顯示頁面,直到OnUnload完成執行。似乎目前唯一可行的方法是啓動一個新線程來完成工作,並允許OnUnload立即完成。但是,我不知道這是否安全。如果服務器在頁面已經發出後執行太長時間,服務器是否會終止該線程?有沒有更正確的方法來實現這一點?在ASP.Net中,如何在發送頁面後運行代碼

+1

你可以使用消息傳遞隊列,並有一個後臺進程照顧它嗎?更像是一個Web角色和一個工作角色如何在Azure中彼此交互? – 2010-08-25 19:27:59

+0

我試圖幫助downvote,但它看起來像某人真的不喜歡這個問題! – mclark1129 2010-08-25 19:35:13

+0

我通常會在沒有回覆的情況下刪除這些問題,如果這些問題太長了。通常情況下,你以後不會得到一個,它有助於限制來自SO的未答覆(並且基本上無用)問題的數量。 – mclark1129 2010-08-25 20:06:28

回答

1

卸載是ASP.NET頁面生命週期的最後一部分。見下面的鏈接:

http://msdn.microsoft.com/en-us/library/ms178472.aspx

這是不是你可以用JavaScript或AJAX嗎?

+0

我特別聲明,我嘗試使用Unload部分,並且瀏覽器仍然不顯示頁面,直到卸載代碼完成。這不是我在Javascript或Ajax中可以做到的,因爲它必須運行服務器端,並且我不能依賴於啓用了Javascript的客戶端來啓動AJAX調用。 – Kibbee 2010-08-25 18:48:51

+1

Kibbee我讀過,但是你沒有說明你知道這是頁面生命週期的最後階段,這就是我提到它的原因。我不認爲它值得-1,但如果你想要幫助你理解asp.net的工作原理,我肯定不會在你的任何問題上發佈任何問題。 – 2010-08-25 18:52:53

+0

對不起,但我覺得downvote「這個答案沒有用」的描述真的應用在這裏。就我個人而言,我發現如果您實際上沒有提供可以解決問題的信息,那麼您應該將其作爲評論。你給的答案只是額外的信息。它不能解決我所遇到的問題。 – Kibbee 2010-08-25 18:59:28

0

如何掛鉤到page.Disposed事件而不是Unload事件?

+0

試了一下。看起來像在代碼執行之前發送頁面時,我現在面臨的問題是它看起來代碼根本沒有運行。雖然它可能會在將來運行,當物體本身被處置時。我希望代碼能夠以更及時的方式執行,而不是當它處理對象時。 – Kibbee 2010-08-25 19:49:55

0

根據您需要做什麼,可以創建一個ISAPI過濾器,以在響應結束時執行某些操作。

2

基比,

嘗試重寫Page.Render方法和沖洗,像這樣的迴應:

Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter) 
    MyBase.Render(writer) 

    Response.Flush() ' Sends all buffered output to the client 

    ' Run some code after user gets their content 
End Sub 

我覺得在這一點上仍然反應是不完整的,但用戶會得到什麼在完成最終代碼的運行之前,該頁面已經呈現。

HTH,

邁克

+0

這按預期工作。利用Repsonse對象,我可以讓瀏覽器接收並呈現內容。然而,問題在於瀏覽器頁面仍顯示爲加載(旋轉圖標/小時玻璃),與頁面加載時類似,即使在收到內容之後。即使在Response.Flush()之後添加Response.Close之後,此行爲仍然存在。也很高興看到在VB.Net中編碼的其他人。似乎.NET中的大部分內容都集中在C#上。 – Kibbee 2010-08-25 23:32:23

+0

我非常肯定,直到整個ASP.net生命週期完成執行,響應才能完全關閉。這包括HAPPApplication.EndRequest事件,其中AFIAK是生命週期中絕對的最後一點(不計算應用程序何時結束)。我認爲上述方法將會在不產生新線程的情況下最接近你想要的。如果你使用多線程,那麼我建議在HttpApplication.EndRequest中產生線程,以避免線程在Response.End()中被中止。 – mclark1129 2010-08-26 18:59:53

0

你可以試試這個解決方案 - Best ASP.NET Background Service Implementation

使用Windows服務並與之連通的通MSMQ可能是一個更爲可靠的解決方案,並可以擴展更好。這將幫助您分離問題,並讓asp.net前端專注於用戶,而Windows服務專注於後臺任務。

如果您正在使用Azure遷移到雲,您可以簡單地將asp.net前端替換爲Web角色,並且帶有工作角色和您的解決方案的Windows服務可以無縫擴展!

0

下面是一個重做方式來做到這一點。有第二個aspx頁面,完成所有「清理」後渲染邏輯。例如,調用一個'cleanup.aspx'。在Page_Load中運行cleanup.aspx你的清理代碼:

public partial class cleanup: System.Web.UI.Page 
{ 
    protected void Page_Load(object sender, EventArgs e) 
    { 
     // do logging blah blah here.... 
    } 
} 

在您的主aspx頁面,有一個JavaScript函數,使一個AJAX調用「cleanup.aspx」。加載頁面後啓用AJAX功能。我建議jQuery的,如果是你的代碼看起來就像這樣:

$(function(){ 
    yourAJAXYFunctionName(); 
}); 

function yourAJAXYFunctionName()() { 
// ajax code here 
// 
$.ajax({ 
    url: "cleanup.aspx", 
    }); 
} 

這樣,你的第一頁的代碼運行,然後在頁面發送給瀏覽器。當頁面呈現給客戶端時,第二個ASPX頁面通過AJAX調用,這對於cleanup.aspx並不重要,它並不在乎它的被調用和頁面加載事件是如何執行的。然後運行您的清理/日誌記錄代碼。

注意事項:客戶端JavaScript是必需的。但是真的到底誰沒有JS呢?另外,您的cleanup.aspx頁面完全從您的主頁面中抽象出來,因此如果您想要使用源於第一頁的cleanup.aspx中的任何對象,那麼您必須將它們存儲在會話或cookie中,或者您可以在AJAX調用中將它們作爲參數傳遞。這需要動態操作AJAX腳本本身,但這並不難。

-1

更好的我想嘗試{Response.End()} catch {} runco​​de();

+1

這不是現在狀態下的答案。請重新格式化。 – simonmorley 2014-08-21 22:38:18

相關問題