【问题标题】:How can i download many images async using WebClient?如何使用 WebClient 异步下载许多图像?
【发布时间】:2016-12-29 15:52:30
【问题描述】:

我想要的是开始下载第一个图像并将其保存到硬盘。 一旦下载完成,progressBar 达到 100% 就开始下载下一张图片。以此类推。

我试过了:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Net;

namespace SatelliteImages
{
    public partial class Form1 : Form
    {
        int count = 0;

        public Form1()
        {
            InitializeComponent();

            ExtractImages ei = new ExtractImages();
            ei.Init();

            startDownload();
        }

        private void startDownload()
        {
            WebClient client = new WebClient();
            client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
            client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
            foreach (string url in ExtractImages.imagesUrls)
            {
                client.DownloadFileAsync(new Uri(url), @"C:\Temp\TestingSatelliteImagesDownload\" + count + ".jpg");
            }
        }

        void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            double bytesIn = double.Parse(e.BytesReceived.ToString());
            double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
            double percentage = bytesIn / totalBytes * 100;
            label1.Text = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
            progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
        }
        void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            label1.Text = "Completed";
            count++;
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}

List imagesUrls 包含类似这种格式的链接,例如第一项:

http://www.sat24.com/image2.ashx?region=eu&time=201612281630&ir=true

如果我会在 chrome 中浏览到这个链接,那就没问题了。 但是当我尝试下载图像并将图像保存在硬盘上时,我遇到了异常:

client.DownloadFileAsync(new Uri(url), @"C:\Temp\TestingSatelliteImagesDownload\" + count + ".jpg");

附加信息:WebClient 不支持并发 I/O 操作。

System.NotSupportedException was unhandled
  HResult=-2146233067
  Message=WebClient does not support concurrent I/O operations.
  Source=System
  StackTrace:
       at System.Net.WebClient.ClearWebClientState()
       at System.Net.WebClient.DownloadFileAsync(Uri address, String fileName, Object userToken)
       at System.Net.WebClient.DownloadFileAsync(Uri address, String fileName)
       at SatelliteImages.Form1.startDownload() in D:\C-Sharp\SatelliteImages\SatelliteImages\SatelliteImages\Form1.cs:line 37
       at SatelliteImages.Form1..ctor() in D:\C-Sharp\SatelliteImages\SatelliteImages\SatelliteImages\Form1.cs:line 27
       at SatelliteImages.Program.Main() in D:\C-Sharp\SatelliteImages\SatelliteImages\SatelliteImages\Program.cs:line 19
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

【问题讨论】:

标签: c# .net winforms


【解决方案1】:

你只能使用 webclient 实例直到它不忙,因为它不支持并发调用。因此,您必须为每次下载使用新的 WebClient 实例,或者在每次下载结束后链接调用,如下所示:

  //On initialize form :
        WebClient client = new WebClient();

   //On start download :

        client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
        client.DownloadFileCompleted += new AsyncCompletedEventHandler(client_DownloadFileCompleted);
        client.DownloadFileAsync(new Uri(url), @"C:\Temp\TestingSatelliteImagesDownload\" + ExtractImages.imagesUrls[currentImageIndex] + ".jpg");
 ...
        void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
if(currentImageIndex<ImageToDownloadCount){
currentImageIndex +=1;
        client.DownloadFileAsync(new Uri(url), @"C:\Temp\TestingSatelliteImagesDownload\" + ExtractImages.imagesUrls[currentImageIndex] + ".jpg");
}

            label1.Text = "Completed";
            count++;
        }

希望对你有帮助。

【讨论】:

    【解决方案2】:

    使用 DownloadFileTaskAsync 进行异步下载。

    public event EventHandler TaskCompleted;
    
        public async void DownloadAsync()
        {
            String[] urls = { "http://media.salon.com/2014/10/shutterstock_154257524-1280x960.jpg",
                                "http://www.samsung.com/us/2012-smart-blu-ray-player/img/tv-front.png" };
            var tasks = urls.Select((url, index) =>
            {
                var fileName = String.Format(@"c:\temp\image-{0}.jpg", index);
                var client = new WebClient();
                return client.DownloadFileTaskAsync(url, fileName);
            });
            await Task.WhenAll(tasks).ContinueWith(x =>
            {
                if (TaskCompleted != null)
                {
                    TaskCompleted(this, EventArgs.Empty);
                }
            });
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多