I am working with Vb.NET Windows Form application and there was a grid on which images are loaded from memory, it was taking too much memory for a fraction of the time, if a low memory at low, sometimes program gets crashed. A solution was proposed to consume less memory by using direct memory stream and load the picture from URL.
But I am using a data grid view, I need to put all my processing in a thread so, it safely loads the pictures and program won't get stuck.
Below is the code for fetching images from URL and attaching it with GridView Cell, anyone guides me how to put into Thread.
Private Function GetBitmapFromLink(ByVal ImagePath As String) As Image
Dim exp As Boolean = False
Try
Dim request As System.Net.WebRequest = System.Net.WebRequest.Create(ImagePath)
Dim response As System.Net.WebResponse = request.GetResponse()
Dim responseStream As System.IO.Stream = response.GetResponseStream()
Dim Img As New Bitmap(responseStream)
If Img IsNot Nothing Then
Return Img
End If
Catch ex As Exception
WriteToLog(ex)
End Try
End Function
'Using here in loop
CType(dr.Cells("img1"), DataGridViewImageCell).Value = GetBitmapFromLink(ImagePath & dtImages.Rows(i)("ImageName"))
here is the comlete code:
Sub SetSource(ByVal dtImages As DataTable)
Try
Dim ImagePath As String = BaseUrl
ImagePath = ImagePath.Replace("/a", "/p") & "vs/"
LockWindowUpdate(Me.Handle)
Try
For Each dRow As DataRow In grdSent.Rows
CType(dRow("img1"), DataGridViewImageCell).Value = Nothing
CType(dRow("img2"), DataGridViewImageCell).Value = Nothing
Next
Catch ex As Exception
End Try
grdSent.Rows.Clear()
Dim i As Integer = 0
While (True)
Dim drIndx As Integer
Dim dr As DataGridViewRow
If (dtImages.Rows.Count > i AndAlso dtImages.Rows(i)("image") IsNot DBNull.Value) Then
drIndx = grdSent.Rows.Add()
dr = grdSent.Rows(drIndx)
Dim ms As New MemoryStream(CType(dtImages.Rows(i)("image"), Byte()))
'CType(dr.Cells("img1"), DataGridViewImageCell).Value = Image.FromStream(ms)
CType(dr.Cells("img1"), DataGridViewImageCell).Value = GetBitmapFromLink(ImagePath & dtImages.Rows(i)("ImageName"))
dr.Cells("img1").Tag = dtImages.Rows(i)("id")
ms.Close()
Else
Exit While
End If
i = i + 1
If (dtImages.Rows.Count >= i) Then
Try
Dim ms As New MemoryStream(CType(dtImages.Rows(i)("image"), Byte()))
'CType(dr.Cells("img2"), DataGridViewImageCell).Value = Image.FromStream(ms)
CType(dr.Cells("img2"), DataGridViewImageCell).Value = GetBitmapFromLink(ImagePath & dtImages.Rows(i)("ImageName"))
dr.Cells("img2").Tag = dtImages.Rows(i)("id")
ms.Close()
Catch ex As Exception
CType(dr.Cells("img2"), DataGridViewImageCell).Value = My.Resources.WhiteDot
dr.Cells("img2").Tag = -1
End Try
Else
Exit While
End If
i = i + 1
End While
If (grdSent.RowCount > 0) Then
'If (grdSentiments.Rows(grdSent.RowCount - 1).Cells("img1").Value Is My.Resources.WhiteDot AndAlso grdSentiments.Rows(grdSent.RowCount - 1).Cells("img2").Value Is My.Resources.WhiteDot) Then
' grdSentiments.Rows.RemoveAt(grdSent.RowCount - 1)
'End If
End If
Catch ex As Exception
WriteToLog(ex)
Finally
LockWindowUpdate(0)
End Try
End Sub
答案 0 :(得分:2)
.NET 3.5
You can do it without changing your function. Just change the way you use it. For example:
Dim t As New Threading.Thread( _
Sub()
'You can start a loop here
Dim url= "some url" 'Get url from cell
Dim image = GetBitmapFromLink(url) 'Get the image from url
Me.Invoke(Sub()
' Use the image here, for example:
Me.BackgroundImage = image 'Assign the image to cell
End Sub)
'End loop here
End Sub)
t.Start()
You can also consider using BackgroundWorker
to run your time-consuming background tasks.
.NET 4.5 and higher
You can make it asynchronous using Async and Await:
Private Async Function GetBitmapFromLink(ByVal ImagePath As String) As Task(Of Image)
Dim request As System.Net.WebRequest = System.Net.WebRequest.Create(ImagePath)
Dim response As System.Net.WebResponse = Await request.GetResponseAsync()
Dim responseStream As System.IO.Stream = response.GetResponseStream()
Dim Img As New Bitmap(responseStream)
Return Img
End Function
In above method, I used GetResponseAsync
instead of GetResponse
and called it using Await
. I also stripped exception handling codes, you can add them again.
When using, the method should be called in a Async method. So if you want to use it in an event handler, for example in Load
event of form, just add Async
keyword to method handler like:
Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim url= "some url"
Dim image = Await GetBitmapFromLink(url)
End Sub