How can I use streams in C # to download multiple images from the internet at once?

I have a Windows Forms Application in .NET 3.5. There is one form with 20 picture boxes. There's also an array with 20 image URLs. The goal is to iterate over an array of urls and load images from the web into image boxes.

I tried to have a standard foreach loop and use the LoadAsync () method of the image window, but it doesn't work. It will load the image for the first 6 image boxes and won't work for the other 14. I believe the reason is due to too many requests at the same time. But I'm not sure.

So, I want to try manual multi-threaded code where I would use the synchronous Load () method for the picture window and allow a maximum of 3 streams loading an image from the internet at the same time.

Any idea on how to implement this? Basically I need to know how to allow three threads at the same time, from the queue for processing.

Thanks!

+1


a source to share


2 answers


BackgroundWorker is a good class for running tasks on background threads in winforms applications. Here's a small sample I wrote for you to demonstrate its use:



public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        // Declare a list of URLs and their respective picture boxes
        var items = new Dictionary<string, PictureBox> 
        { 
            { "http://www.google.com/logos/spring09.gif", new PictureBox() { Top = 0, Width = 300, Height = 80  } }, 
            { "http://www.google.com/logos/stpatricks_d4gwinner_eo09.gif", new PictureBox() { Top = 100, Width = 300, Height = 80 } },
            { "http://www.google.com/logos/schiaparelli09.gif", new PictureBox() { Top = 200, Width = 300, Height = 80 } },
            { "http://www.google.com/logos/drseuss09.gif", new PictureBox() { Top = 300, Width = 300, Height = 80 } },
            { "http://www.google.com/logos/valentines09.gif", new PictureBox() { Top = 400, Width = 300, Height = 80 } },
            { "http://www.google.com/logos/unix1234567890.gif", new PictureBox() { Top = 500, Width = 300, Height = 80 } },
            { "http://www.google.com/logos/charlesdarwin_09.gif", new PictureBox() { Top = 600, Width = 300, Height = 80 } },
        };

        foreach (var item in items)
        {
            var worker = new BackgroundWorker();
            worker.DoWork += (o, e) =>
            {
                // This function will be run on a background thread
                // spawned from the thread pool.
                using (var client = new WebClient())
                {
                    var pair = (KeyValuePair<string, PictureBox>)e.Argument;
                    e.Result = new KeyValuePair<PictureBox, byte[]>(pair.Value, client.DownloadData(pair.Key));
                }
            };
            worker.RunWorkerCompleted += (o, e) => 
            {
                // This function will be run on the main GUI thread
                var pair = (KeyValuePair<PictureBox, byte[]>)e.Result;
                using (var stream = new MemoryStream(pair.Value))
                {
                    pair.Key.Image = new Bitmap(stream);
                }
                Controls.Add(pair.Key);
            };
            worker.RunWorkerAsync(item);
        }
    }
}

      

+8


a source


I'd take a look at the Synchronized Queue collection available from System.Collections if you want to use a multi-thread queue.



Also, the following link is a great introduction to streams in C #. Discovers what threads are, when to use them (and when they are not), how to start and stop threads and how to make the core thread safe, and more: Threading in C #

+1


a source







All Articles