Как я могу использовать потоки в C # для загрузки нескольких изображений из Интернета одновременно? - PullRequest
1 голос
/ 25 мая 2009

У меня есть приложение Windows Forms в .NET 3.5. Есть одна форма с 20 картинными коробками. Также есть массив с 20 URL-адресами изображений. Цель состоит в том, чтобы перебрать массив URL и загрузить изображения из Интернета в графические блоки.

Я попытался использовать стандартный цикл foreach и использовать метод LoadAsync () с графическим блоком, но он не работает. Он загрузит изображение для первых 6 графических блоков и завершит работу для остальных 14. Я считаю, что причина связана с слишком большим количеством запросов одновременно. Но я не уверен.

Итак, я хочу попробовать ручной многопоточный код, в котором я бы использовал синхронный метод Load () графического блока и позволял максимум 3 потокам загружать изображение из Интернета одновременно.

Есть идеи, как это реализовать? По сути, мне нужно знать, как разрешить обработку 3 потоков одновременно из очереди.

Спасибо!

Ответы [ 2 ]

8 голосов
/ 25 мая 2009

BackgroundWorker - хороший класс для запуска задач в фоновых потоках в приложениях winforms. Вот небольшой пример, который я написал для вас, чтобы продемонстрировать его использование:

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);
        }
    }
}
1 голос
/ 25 мая 2009

Я бы взглянул на коллекцию Synchronized Queue , доступную в System.Collections, если вы хотите использовать очередь с несколькими потоками.

Кроме того, следующая ссылка является отличным введением в темы в C #. Описывает, что такое потоки, когда их использовать (а когда нет), как запускать и останавливать потоки и как сделать ваши основные операции потокобезопасными и многое другое: Потоки в C #

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...