注:該問題已解決,詳見終於解決“百年一遇”奇怪問題。
問題原因
經過昨天一天的奮戰,終於在吃晚飯前找到了"百年一遇"奇怪問題的原因。(問題詳情見前一篇博文:百年一遇的奇怪問題:當IE遇上.NET Framework 4.5)
問題原因是:當服務器安裝了 .NET Framework 4.5 之后,在IE中,如果 ASP.NET MVC 處理的 ajax 請求未執行完成時,連接被中斷(比如F5刷新瀏覽器),接下來的請求就會被卡住。
問題驗證
用 IE 訪問閃存(http://home.cnblogs.com/ing/),按 F12 打開開發者工具,等所有 ajax 請求執行完成再刷新瀏覽器,問題就不會出現。
我們在測試環境中,取消所有 ajax 請求,問題就不會出現。
問題分析
為什么 ajax 請求被中斷后會出現這個問題?
我的猜測是:ajax 請求被中斷后,服務器端 ASP.NET Runtime 處理該請求的線程繼續保留着(可能在刷新時, IE 繼續保持着連接),接下來的請求繼續由這個線程處理,於是卡住。所以,重啟 IE 問題會消失就是因為這時 IE 發起了新的連接,服務器端用新的線程進行處理,這同時也解釋了第一次請求總是不會出現問題。
下面針對前一篇博文中問題的五個奇怪之處逐一進行分析:
1、“問題奇怪之一:服務器是微軟的 ASP.NET 環境,出問題的不是其他瀏覽器,而是微軟自己的 IE 瀏覽器。”
猜測:在刷新時,IE 可能與其他瀏覽器的處理方式不一樣,IE 會繼續保持着同一個 HTTP 連接。服務器端 ASP.NET Runtime 對這個連接使用之前為之服務的一個線程處理(可能是 .NET Framework 4.5 的一個改變)。
2、“問題奇怪之二:IE 第一次請求不會出現問題,問題只出現在后續請求中。”
因為問題只會在 ajax 請求被中斷后的請求中出現。
3、“問題奇怪之三:同一台服務器,有多個站點,只有這一個站點會出現這個問題。同一個站點(home.cnblogs.com),只有主頁與閃存相關頁面會出現這個問題。”
出現問題的頁有個特征 —— ajax 請求特別多,問題可能與 ajax 請求的數量有關。
4、“問題奇怪之四:WebForms 與 MVC 都會出現這個問題。”
問題在服務器端 ASP.NET Runtime 處理該請求的線程,所以與是 WebForms 還是 MVC 無關。
5、“問題奇怪之五:在 Global.asax 中取消所有 MVC 的路由注冊(routes.MapRoute),問題就消失。”
由於 ajax 請求是由 MVC 處理的,取消 MVC 的路由注冊也就不存在 ajax 請求被中斷的情況。
繼續奮戰
進一步的原因以及解決方案還要繼續努力研究。。。
最新進展
將 ajax 請求的處理由 MVC 改為 Web Service(.asmx) 之后,問題不再出現。由此可見,與瀏覽器、與 js 一點關系沒有。