現象:
近來在程式中使用了水晶報表——在一個頁面中用水晶報表產生PDF文檔。程式運行良好,但有一個很奇怪的問題:程式運行一段時間後就必須重起一下IIS。
分析過程:
我用Process Explorer對IIS進程檢查發現進程裡有很多檔案沒有釋放。如:
IIS進程中充斥了很多臨時檔案沒有釋放。
解決方案:
在用到水晶報表的頁面事件Page_Unload中,將水晶報表相關對象釋放。
1Imports DataBean
2Imports DataSet1
3Imports System.Data
4Imports CrystalDecisions.CrystalReports.Engine
5Imports CrystalDecisions.Shared
6
7Partial Class _CrystallReportTestingClass _CrystallReportTesting
8 Inherits System.Web.UI.Page
9
10 Dim oRpt As New ReportDocument
11 Protected Sub Page_Load()Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
12 '' 水晶報表綁定
13 oRpt.Load(Server.MapPath("CrystalReport4.rpt"))
14 oRpt.SetDataSource(GetDataSourceFromOracle())
15 '' 設定水晶報表的ReportSource
16 CrystalReportViewer1.ReportSource = oRpt
17 End Sub
18
19 Protected Sub Page_Unload()Sub Page_Unload(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Unload
20 oRpt.Close() ''釋放水晶報表對象
21 oRpt.Dispose()
22 System.GC.Collect(0)
23 End Sub
24End Class
25
小插曲:
在調式過程中,我發現每當頁面載入時執行Page_Load事件之後(如果沒有其它代碼),將會緊接著執行Page_Unload事件。這怎麼回事?我直覺地以為Page_Unload會在用戶端將網頁關閉時觸發。
這也是我記錄這個事件的主要原因:我總是不自然地將Web的編程模式理解為Windows編程模式。將http無狀態性本質遺忘。主觀臆斷,不經思考地認為Page_Unload會在用戶端將網頁關閉時觸發——這怎麼可能呢?對於Asp.net執行模型來說,在IIS接到一個Get/Post請求時初始化一個與訪問相關的頁面類來處理該請求。並在處理完成後產生的HTML發送回用戶端,之後該頁面類等待被記憶體回收。
轉一段網上的回帖,很好的回答了該問題:
It's confusing for windows developer. Remember about Unload event defenition. "Occurs when the server control is unloaded from memory" after each load or post back in server side all controls Unloaded from memory. Remember we talking about web application all controls get alived by request and died when response create and send to client.So thats why after load event Unload event called.