2014-05-07 46 views
0

我使用以下代碼從SQLite數據庫填充ImageList,並將圖像存儲爲blob。System.IO.MemoryStream的有效使用(或替代方案)

Public Sub populateImagesStyles() 

    ShoeImages1.Images.Clear() 
    StyleImagesLView.Items.Clear() 

    Dim s As SQLiteDataReader 
    Dim rcount As Integer = 0 
    dbLocalQuery = New SQLiteCommand("SELECT id, image FROM tblImages", dbLocal) 
    s = dbLocalQuery.ExecuteReader() 

    While s.Read() 
     rcount += 1 
     ShoeImages1.Images.Add(CStr(s("id")), byte2img(s("image"))) 
     StyleImagesLView.Items.Add(CStr(s("id")), CStr(s("id"))) 

    End While 
    s.Close() 

這裏是byte2img功能...

Public Function byte2img(ByVal imgByte As Byte()) As Image 
    Dim imgMemoryStream As System.IO.MemoryStream = New System.IO.MemoryStream(imgByte) 
    byte2img = Drawing.Image.FromStream(imgMemoryStream) 
End Function 

該數據庫包含了超過250張,這個過程完成兩次load把兩個不同的ImageList,因爲我需要在兩個顯示的圖像不同的尺寸。

當進程在加載表單時運行時,它會導致進程消耗800MB到1GB的系統內存,除非我再次從表單控件再次手動運行進程,這似乎觸發了垃圾回收。

單步加載過程很明顯,它是導致內存使用率升級的byte2img進程 - 緩解此問題的最佳方法是什麼?

此外,如果任何人都可以想到一個更有效的過程來執行此操作,我全部都是耳朵。圖像必須存儲在數據庫文件中,因爲我需要能夠將.db文件打包並在臨時通知時將其發送到遠程位置,所以我不能用圖像混淆文件夾。

所有幫助表示讚賞。

+0

您是否需要一次加載所有圖像?你可以在你的表單上使用分頁,以便獲得前10張圖像,然後繼續下一個10等...? – LightningShield

+0

如果您的圖像存儲在數據庫中,爲什麼將它們全部加載到應用程序中?你不能根據需要從數據庫中獲取它們,也許一旦它們被檢索到就可以保存它們,所以不需要重複。 – Plutonix

+0

圖像被讀出到兩個ImageList中,詳見文章。這是數據庫CRUD功能的一部分 - 用戶可以修改記錄並通過點擊圖像選擇要與其他數據關聯的圖像。 如果在滾動到當前的ListView底部之後有數據分頁到「ImageList」或獲取更多數據的方式,那麼我就是耳朵。 – Optimaximal

回答

0

好的,我找到了一個似乎可行的解決方案/解決方法 - 當用戶訪問ImageList所在的特定TabPage時,調用PopulateImageStyles子。

由於某些任意的原因,當以這種方式運行時(如上所述,當在表單上調用時),進程永遠不會消耗超過50-60 MB的工作內存。

我將添加一個Background Worker,以便該過程可以在不掛表單的情況下執行。

4

您正在創建大量內存流而不會對其進行處理。試試這個:

Public Function byte2img(ByVal imgByte As Byte()) As Image 
    Dim img As Image 

    Try 
     Using ms As New MemoryStream(imgbyte) 
      img = Drawing.Image.FromStream(ms) 
     End Using  ' auto dispose of the MS 
    Catch ex As Exception 
     ' report possibly bad/missing imgByte() 
     ' resulting in an error in either place 
    End Try 

    Return img 
End Function 

一個不精確的方法來檢測這種事情是看TaskManager中的HANDLES計數。

+0

還要確保Drawing.Image.FromStream可能會拋出一個ArgumentException。也許還提到垃圾收集器。 –

+0

@FabianBigler好點;我個人會在調用這個函數之前檢查數據庫列,但是可能會出現亂碼或不完整。 GC怎麼樣? – Plutonix

+0

加載這段代碼的速度肯定快很多,但運行內存使用率仍然在850和950 MB之間,直到我重複Populate過程,這會導致它下降到更合理的〜150 MB。 任何想法? – Optimaximal