大叔手記(9):小心使用IHttpHandler下的IsReusable屬性
2011-12-17 20:39 湯姆大叔 閱讀(17973) 評論(14) 收藏 舉報(bào)簡介
我們平時(shí)在開發(fā)的時(shí)候,經(jīng)常做一些自定義的HttpHandler,每次再繼承IHttpHandler接口的時(shí)候,都要設(shè)置IsReusable的值,通常我們都是設(shè)置返回true,可是我們要小心這個(gè)返回值,因?yàn)樵O(shè)置為true的時(shí)候有很多前提條件,其中最重要的2個(gè)是:
- 線程要安全
- 一個(gè)請求的HttpHandler實(shí)例下的狀態(tài)或上下文信息不能被另外一個(gè)請求共享。
再深一點(diǎn)
MSDN對IsReusable的解釋非常少:獲取一個(gè)值,該值指示其他請求是否可以使用 IHttpHandler 實(shí)例。
首先,IsReusable這個(gè)屬性其實(shí)用來指明IHttpHandler實(shí)現(xiàn)類的實(shí)例是否可以被用來處理多個(gè)請求。當(dāng)通過ASP.NET 管道處理時(shí),每個(gè)客戶端請求被服務(wù)端認(rèn)為是一個(gè)工作者線程。因此,如果我們設(shè)置 IsReusable = true 時(shí),我們需要確信ProcessRequest 方法是線程安全的。 ProcessRequest 應(yīng)該不會(huì)依賴任何有可能被其他請求修改的狀態(tài)值。當(dāng)你的IHttpHandler實(shí)現(xiàn)類忙于做初始化時(shí),否則你無需介意IsReusable 返回的是true 或者 false。
另外,由于HttpHandler實(shí)例是由HttpHandlerFactory來創(chuàng)建的,而HttpHandlerFactory創(chuàng)建HttpHandler實(shí)例的時(shí)候會(huì)將上下文信息HttpContext作為參數(shù)傳進(jìn)去,如果多個(gè)工作者線程共享這個(gè)實(shí)例的話,那就不能都依賴HttpContext.Request內(nèi)容,因?yàn)橐蕾嚵耍歉鱾€(gè)請求就亂了,比如你通過一個(gè)Request參數(shù)設(shè)置Httphandler的一個(gè)屬性值,然后其他線程在調(diào)用的時(shí)候就有可能用到這個(gè)值,(但是可以利用Request參數(shù)去分別處理自己的邏輯,只要不共享就行),再比如我們?nèi)绻谧龆嘤脩粜畔⒌臅r(shí)候,如果一個(gè)用戶能管理另外一個(gè)用戶的資源的話,那就有問題了。
微軟之所以暴露這個(gè)屬性給我們,因?yàn)閯?chuàng)建HttpHandler的開銷比較大,當(dāng)IsReusable 為真時(shí), CLR會(huì)維護(hù)一個(gè)對象池,進(jìn)去重用,但同時(shí)它也應(yīng)該是無狀態(tài)的。
總結(jié)
所以說在設(shè)置IsReusable為true的時(shí)候,一定要保證線程安全,并且不依賴Request項(xiàng),當(dāng)然也不應(yīng)該有成員變量,因?yàn)槌蓡T變量在同一個(gè)實(shí)例下是隨意可用的。
另外還有一點(diǎn)是,盡量不要使用.ashx文件格式,因?yàn)樗窃诘谝黄谡埱蟮臅r(shí)候才編譯,速度自然沒有預(yù)先編譯快了,所以建議在web.config里直接指定所對應(yīng)的HttpHandler。
同步與結(jié)束語
本文已同步至目錄索引:《大叔手記全集》
大叔手記:旨在記錄日常工作中的各種小技巧與資料(包括但不限于技術(shù)),如對你有用,請推薦一把,給大叔寫作的動(dòng)力
浙公網(wǎng)安備 33010602011771號