2010-07-23 45 views
7

自從我開始編寫經典的ASP 12(或多年前)以來,我就一直在探討這個問題,而且我從未找到一個好的解決方案,因爲ASP和ASP.NET的體系結構一直都是不好的做法沼澤,魔法共享單身等。我最大的問題是與HttpApplication對象與其非事件事件(Application_StartApplication_End等)。Application_Start與OnInit與構造函數

如果你想在HTTP應用程序的整個生命週期內做一次東西,那麼Application_Start是明顯的地方。對?不完全是。首先,這不是一個事件本身,它是一種神奇的命名約定,當遵循這個約定時,會爲每個由IIS創建的AppDomain調用該方法一次。

除了神奇的命名規則是一種可怕的做法,我開始認爲這可能是一個原因,在HttpApplication對象上不存在Start事件。所以我嘗試了一些確實存在的事件,例如Init。那麼,這也不是一個真正的事件,它是一種可重複使用的方法,這是下一個最好的事情。

看起來,HttpApplication對象的每個實例化都會調用Init()方法,該方法發生的次數遠遠超過每個AppDomain一次。這意味着我不妨將我的啓動邏輯放在HttpApplication對象的構造函數中。

現在我的問題是,爲什麼我不應該把我的啓動邏輯放在構造函數中?爲什麼連Init()都存在,我需要關心Application_Start?如果我這樣做,任何人都可以解釋爲什麼在HttpApplication對象中沒有針對此僞事件的適當事件或可覆蓋的方法?

而且任何人都可以向我解釋爲什麼在一個典型的ASP.NET應用程序的8個實例我HttpApplication創建(這會使構造和Init運行同樣多的時間當然,這可以通過鎖定減輕和一個叫做initialized的共享靜態布爾值),當我的應用程序只有一個AppDomain時?

+0

可能需要在Application_Start中完成,以便框架可以設置所有這些魔術共享對象。也許這個類在這之前就被觸及了,靜態構造函數會運行得太早。 – 2014-05-02 20:20:51

+0

@JoeKoberg,這是一個很好的觀點。當然,對靜態構造函數進行調用的時間比對顯式方法調用的控制要少。不過,我仍然沒有看到'Init()'的必要性。而'Application_Start'和'Application_End'應該仍然是正確的事件。 – 2014-05-05 08:44:51

回答

3

調用Application_Start第一次創建HttpApplication的一個實例,但不是在後續的實例上看起來有點破解。也許微軟不想向那些並不真正想知道的人解釋一個靜態構造函數的概念。

但是,Application_End()似乎是必需的,因爲沒有靜態析構函數/終結器的C#等價物。隨着黑客行動,這並沒有那麼糟糕。它只是聞起來有點有趣。

+0

我同意Application_End()是必需的,但爲什麼不是它(也不是Application_Start)您可以聽到的適當事件?我瞭解與傳統ASP的背景兼容性,但未公開事件對我來說沒有多大意義。 – 2011-06-01 09:05:57

0

爲每個併發請求創建一個HttpApplication對象。這是ASP.NET創建的每個線程都獲得自己的HttpApplication實例。實例被重複用於後續請求,其方式與線程池中重用線程的方式相同。

使用Init方法來初始化HttpApplication上的實例字段,因爲如果它們在Application_Start事件中完成,它們只會初始化爲第一個實例。

+1

但是,爲什麼要使用Init()方法而不是構造函數? Init()方法給你的構造函數不是什麼? – 2011-06-01 08:51:52

4

Asp.Net運行庫保留一個HttpApplication對象池。每個.aspx請求都由從池中分配的單個對象(您的案例中的8個對象)處理。

對於你的問題的答案,Application_Start事件的確被調用,但僅用於HttpApplication的第一個實例,而不是後續的實例,因此,無論何時啓動應用程序或應用程序池,都可以確保只調用一次的IIS重新啓動。同樣,Application_OnEnd事件(最後一個實例)

與此同時,在HttpApplication對象的每個實例上都調用Init()和Dispose()。這將在每個實例a.k.a.每個請求上被調用。

爲什麼他們這樣做..?也許是爲了平衡性能和內存優化。

希望我回答你的問題。

+0

感謝您的回答。不過,您在回覆中沒有提到構造函數。當你可以在構造函數中做同樣的事情時,爲什麼還需要Init(),並將私有字段更改爲'readonly'? 爲什麼'Application_Start'和'Application_End'沒有適當的事件可以通過適當的事件處理程序來掛鉤?另外,每個應用程序域或每個工作進程會調用一次嗎? – 2010-08-10 11:24:50

+0

每個工作者進程一次,對不對?因爲您可以在自己的工作進程中創建AppDomain而無需Application_Start觸發。通常,如果您不創建自己的應用程序域,那麼是的,它應該是每個AppDomain以及工作進程afaik。 – Henrik 2010-11-20 15:29:10