[VBNET] WebBrowser Control 壓抑記憶體膨脹

話說,我們在現地有一些 IPCam 在不同地區,分散在中南部各處,為了方便監測,定時透過最廉價的 ADSL 丟照片回 Web Server ,再由網頁撥放,打算在 1920×1080 的電視牆輪播各區的狀況,下圖是 3×2 的輪播圖之一:

現場影像監測

現場影像監測

網頁在 IE10@Win7x64 下開發,開發前已經預想到 IE 可能會快取的問題,所以在圖片輸出那邊特別針對快取做定義,禁止本機快取儲存,並且在 HTTP Header 加入有效期、檔案時間等資訊,確保瀏覽器能分辨圖片時間不同,重新下載。

用 IE10 觀看都沒啥問題,由於要在同一台電視輪播多個畫面,含單一案場的放大圖片,所以用 VBNET 嵌入 WebBrowser Control 來播放,這樣就很好控制全螢幕的撥放時間跟順序。

用 WebBrowser Control 一跑,馬上發生第一個問題,照片被快取,畫面不會動。雖然資料時間一直在更新,但是照片一直不換,所以先在圖片網址加上時間戳記。沒錯,這樣的確不會再被快取,但是接著發生跑個半天記憶體就爆了,原來 WebBrowser Control 不會自動釋放記憶體。

一開始放棄時間戳記,改調整各種快取設定,總是無效,甚至透過 AJAX 設定 XmlHttpRequest 中的 HTTP Header ,讓 AJAX 抓下最新的圖片,再看看 WebBrowser Control 是否能正確撥放被 AJAX 快取過後的圖片。從封包檢視器確認了,AJAX 的確抓了最新的畫面,但是 WebBrowser Control 就是撥放他自己快取的那個。

最後只好回頭查 WebBrowser Control 的處理方式。

WebBrowser Control 這邊有兩種方式:

1. 透過程式碼刪除快取。不知道是不是我都撥放同一張圖,所以網址不變,所以 WebBrowser Control 也沒重新載入圖片。有興趣可參考:

如何清除快取,當您的應用程式裝載在 Visual Basic.NET 中的 WebBrowser 控制項

2. 透過程式碼動態壓縮記憶體,也就是配合時間戳記來顯示新的圖片。

這部分可以搜尋 WebBrowser memory leak ,就可以找到了。大部分軟體都是透過 SetProcessWorkingSetSize 這個 API ,看 MSDN 這個 API 也可以呼叫 EmptyWorkingSet 取代。所以把專案插入我專門放這類型 API 的模組檔,忽然發現,裡面有個寫好的,我還已經放在我的網站上:

程序 CompressProcessMemory 指定程序記憶體壓縮整理,移除目前未使用的工作區

查了一下使用情形,發現是在 2007 年的一個專案,因為在 Windows Form 用 PictureBox 大量輪播圖片後,也會有類似記憶體不斷增加的情形,所以當時就用了這方法。 Orz

考慮到相關網誌談到,有些人因為 IE8 的版本,可能只使用 EmptyWorkingSet 還不夠,所以最終在排程中,每一輪是呼叫這樣的內容:

程式碼
     CompressProcessMemory()

GC.AddMemoryPressure(8192)

GC.Collect()

GC.WaitForPendingFinalizers()

GC.Collect()

GC.WaitForFullGCComplete()

GC.Collect()

GC.RemoveMemoryPressure(8192)

 

再跑 WebBrowser Control 就可以看到記憶體穩定的上下擺動,燒機跑了 4 天還維持在原先擺動的範圍。

終於搞定收工了。

廣告
Categories: 工作點滴, 技術分享 | 發表留言

文章分頁導航

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s

在WordPress.com寫網誌.

%d 位部落客按了讚: