【问题标题】:How can I use threads in C# to load several images from the web at once?如何使用 C# 中的线程一次从 Web 加载多个图像?
【发布时间】:2023-04-11 04:15:01
【问题描述】:

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

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

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

关于如何实现这一点的任何想法?基本上我需要知道如何同时处理队列中的 3 个线程。

谢谢!

【问题讨论】:

    标签: c# winforms multithreading asynchronous


    【解决方案1】:

    如果您希望使用具有多个线程的队列,我会查看 System.Collections 提供的 Synchronized Queue 集合。

    此外,以下链接是对 C# 中线程的精彩介绍。涵盖什么是线程、何时使用(以及何时不使用)、如何启动和停止线程以及如何使您的基本操作线程安全等等:Threading in C#

    【讨论】:

    • 谢谢,这是一个不错的页面。我刚刚阅读了有关 Semaphore 的信息,我将尝试使用它来实现我所需要的。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-24
      • 2012-07-30
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      • 2011-07-15
      • 2021-10-07
      • 1970-01-01
      相关资源
      最近更新 更多