如何在C#中使用线程一次从Web加载多个图像?

Leo*_*eoD 1 c# multithreading asynchronous winforms

我在.NET 3.5中有一个Windows窗体应用程序.有一个表格有20个图片框.还有一个包含20个图像URL的数组.目标是遍历URL的数组并将图像从Web加载到图片框中.

我尝试使用标准的foreach循环并使用图片框LoadAsync()方法,但它不起作用.它将为前6个图片框加载图像而对另一个图片框失败.我认为原因与同时有太多请求有关.但我不确定.

所以我想尝试一个手动多线程代码,我在其中使用图片框的同步Load()方法,并允许最多3个线程同时从Web加载图像.

有关如何实现这一点的任何想法?基本上我需要知道如何从队列中同时允许3个线程进行处理.

谢谢!

Dar*_*rov 8

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)