Image loading

Bocky

Member
Joined
Nov 7, 2008
Messages
5
Programming Experience
1-3
I am creating an image gallery in VS2008 where each image is streamed from the web using the following code..

VB.NET:
    Public Sub LoadImageFromUrl(ByRef url As String, ByVal pb As PictureBox)
        Dim request As Net.HttpWebRequest = DirectCast(Net.HttpWebRequest.Create(url), Net.HttpWebRequest)
        Dim response As Net.HttpWebResponse = DirectCast(request.GetResponse, Net.HttpWebResponse)
        Dim img As Image = Image.FromStream(response.GetResponseStream())
        response.Close()
        pb.SizeMode = PictureBoxSizeMode.StretchImage
        pb.Image = img
    End Sub
VB.NET:
    Private Sub Button1_Click

        Dim Y As Integer = 0

        For i = 0 To 2

            Dim thumb As New PictureBox

            With thumb

                .Size = New System.Drawing.Size(300, 100)
                .Location = New System.Drawing.Point(2, Y)
                .Name = "thumb" & i

                Select Case i
                    Case 0
                       LoadImageFromUrl("http://picture0.jpg", thumb)
                    Case 1
                        LoadImageFromUrl("http://picture1.jpg", thumb)
                    Case 2
                        LoadImageFromUrl("http://picture2.jpg", thumb)
                End Select

                Controls.Add(thumb)

            End With

            Y += 200

        Next i

    End Sub

However the problem is that the user cannot interact with the form until each image has loaded (when the loop ends). Ideally I would like to be able to select an image before the following 20+ have loaded otherwise the user could be sitting around for a good 5 minutes even though they may only want to select the first image lol :S

Any ideas are much appreciated :)
 
I would use WebClient Class (System.Net) because it makes requests simpler, has async functionality including thread safe events and cancelling of downloads. When downloading async you need one WebClient instance for each request, so for management this sample adds them to a List. The Pictureboxes I added to a FlowLayoutPanel for simplicity. I also included code to cancel remaining downloads, and a basic progress indicator.
VB.NET:
Private clients As New List(Of Net.WebClient)

Private Sub LoadImageFromUrlAsync(ByVal url As String, ByVal index As Integer)
    Dim client As New Net.WebClient
    clients.Add(client)
    AddHandler client.DownloadDataCompleted, AddressOf client_DownloadDataCompleted
    client.DownloadDataAsync(New Uri(url), index)
End Sub

Private Sub client_DownloadDataCompleted(ByVal sender As Object, ByVal e As System.Net.DownloadDataCompletedEventArgs)
    Dim client As Net.WebClient = CType(sender, Net.WebClient)
    clients.Remove(client)
    client.Dispose()
    RemoveHandler client.DownloadDataCompleted, AddressOf client_DownloadDataCompleted
    If Not e.Cancelled AndAlso e.Error Is Nothing Then        
        Dim pb As New PictureBox
        With pb
            .Size = New System.Drawing.Size(300, 100)
            .Name = "thumb" & CStr(e.UserState)
            .Image = Image.FromStream(New IO.MemoryStream(e.Result))
            .SizeMode = PictureBoxSizeMode.Zoom
        End With
        Me.FlowLayoutPanel1.Controls.Add(pb)
        Me.ProgressLabel.Text = clients.Count.ToString & " downloads remaining."
    End If
End Sub

Private Sub CancelAll()
    For Each c As Net.WebClient In clients
        c.CancelAsync()
        c.Dispose()
    Next
    clients.Clear()
End Sub
Starting the load:
VB.NET:
For i = 0 To 20        
    LoadImageFromUrlAsync(String.Format("http://picture{0}.jpg", i), i)
Next i
Me.ProgressLabel.Text = clients.Count.ToString & " downloads remaining."
 
WOAH thanks heaps JohnH,

thats exactly what I want to do with explanations, improvements and working code! :D

Thanks so much!
 
Back
Top