我创建了一个名为SiteDownload
的新类,并添加了一些下载图像的链接:
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
public class SiteDownload
{
public static List<string> Sites()
{
List<string> list = new List<string>();
list.Add("mysite.com/sites/default/files/1231105.gif");
list.Add("mysite.com/sites/default/files/1231040.gif");
return list;
}
public static async Task<List<Website>> ParallelDownload(IProgress<ProgressReport> progress, CancellationTokenSource cancellationTokenSource)
{
List<string> sites = Sites();
List<Website> list = new List<Website>();
ProgressReport progressReport = new ProgressReport();
ParallelOptions parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = 8;
parallelOptions.CancellationToken = cancellationTokenSource.Token;
await Task.Run(() =>
{
try
{
Parallel.ForEach<string>(sites, parallelOptions, (site) =>
{
Website results = Download(site);
list.Add(results);
progressReport.SitesDownloaded = list;
progressReport.PercentageComplete = (list.Count * 100) / sites.Count;
progress.Report(progressReport);
parallelOptions.CancellationToken.ThrowIfCancellationRequested();
});
}
catch (OperationCanceledException ex)
{
throw ex;
}
});
return list;
}
private static Website Download(string url)
{
Website website = new Website();
WebClient client = new WebClient();
website.Url = url;
website.Data = client.DownloadString(url);
return website;
}
public class Website
{
public string Url { get; set; }
public string Data { get; set; }
}
public class ProgressReport
{
public int PercentageComplete { get; set; }
public List<Website> SitesDownloaded { get; set; }
}
}
在form1
中:
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using static HttpClientFilesDownloader.SiteDownload;
namespace HttpClientFilesDownloader
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
void PrintResults(List<Website> results)
{
richTextBox1.Text = string.Empty;
foreach (var item in results)
richTextBox1.Text += $"{item.Url} downloaded: {item.Data.Length} characters long.{Environment.NewLine}";
}
void ReportProgress(object sender, ProgressReport e)
{
progressBar1.Value = e.PercentageComplete;
label1.Text = $"Completed: {e.PercentageComplete} %";
PrintResults(e.SitesDownloaded);
}
CancellationTokenSource cancellationTokenSource;
private async void button1_Click(object sender, EventArgs e)
{
try
{
cancellationTokenSource = new CancellationTokenSource();
Progress<ProgressReport> progress = new Progress<ProgressReport>();
progress.ProgressChanged += ReportProgress;
var watch = Stopwatch.StartNew();
var results = await SiteDownload.ParallelDownload(progress, cancellationTokenSource);
PrintResults(results);
watch.Stop();
var elapsed = watch.ElapsedMilliseconds;
richTextBox1.Text += $"Total execution time: {elapsed}";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
cancellationTokenSource.Dispose();
}
}
private void button2_Click(object sender, EventArgs e)
{
if (cancellationTokenSource != null)
cancellationTokenSource.Cancel();
}
}
}
设计者
当我点击START按钮时,没有任何React。我没有看到progressBar
得到任何进程,label1
没有更新,RichTextBox中没有任何内容。它只是没有下载图像。
我没有收到任何错误,只是无法下载。
我把这个例子从这个网站,而不是下载网站/s我试图下载图像文件,并将它们保存在硬盘上的图像:
example
我还需要像使用webclient一样添加header:
webClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0 Chrome");
但不确定如何将头添加到HttpClient。
1条答案
按热度按时间uemypmqf1#
HTTP资源下载器的示例。
这个类是针对.Net 6+的,因为它使用Parallel.ForEachAsync()。
record keyword需要C# 9+.
Nullable
已启用我尽量保持你在OP中使用的结构
若要开始下载资源集合,请调用静态
Download()
方法,传递IProgress<ProgressReport>
委托、表示资源URL的字符串集合和CancellationTokenSourceReportProgress()
方法会将ProgressReport
记录封送行程至UI执行绪。它会指涉网站记录,其中包含目前资源的URL、影像(在此范例中)字节、Completed
状态,以及资源因某种原因下载失败时所掷回的例外状况。如果同时取消下载,例外状况原因将是The operation was canceled
。它还以百分比的形式返回下载的总体进度。
请注意,取消操作时进度过程也会完成,因为您可能想知道在取消操作之前哪些资源已完成,哪些资源无法完成
**注意:**静态
Download()
方法不是线程安全的,即您不能并发调用此方法,例如,同时下载多个资源列表。再次调用该方法之前,请检查
IsBusy
属性。您可以按如下方式设置表单:
logger
)以显示正在下载的资源的状态btnStartDownload
)btnStopDownload
)progressBar
),用于显示总体进度请注意,使用活动(未配置)调试器时,您可能会收到抛出异常的通知,因此可以使用
CTRL + F5
运行项目它是这样工作的: