views:

792

answers:

2

Hi all,

I have a windows forms application in .NET 3.5. There's one form with 20 picture boxes. There's also an array with 20 image URL's. The goal is to loop through the array of URL's and load the images from the web into the picture boxes.

I tried having a standard foreach loop and use the picture box LoadAsync() method, but it doesn't work. It will load the image for the first 6 picture boxes and fail for the other 14. I believe the reason has something to do with too many requests at the same time. But I'm not sure.

So I want to try a manual multithreading code, where I'd use the synchronous Load() method of the picture box, and allow a maximum of 3 threads loading the image from the web at the same time.

Any idea on how to implement this? Basically I need to know how to allow 3 threads at the same time, from a queue to be processed.

Thanks!

+1  A: 

I'd have a look at the Synchronized Queue collection available from System.Collections, if you are looking to use a Queue with multiple threads.

Also, the following link is a great introduction to threads in C#. Covers what threads are, when to use them (and when not to), how to start and stop threads and how to make your basic operations thread safe and much more: Threading in C#

Simucal
Thanks, it's a nice page. I just read about the Semaphore and I'll try to use it to achieve what I need.
LD2008
+6  A: 

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 usage:

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);
        }
    }
}
Darin Dimitrov