继续上一篇 一个简单的利用 WebClient 异步下载的示例(二) 后,继续优化它。

1. 直接贴代码了:

DownloadEntry:

    public class DownloadEntry
{
public string Url { get; set; } public string Path { get; set; } /// <summary>
/// 当前处理的数据
/// </summary>
public object Data { get; set; } public DownloadEntry(string url, string savedPath)
: this(url, savedPath, null)
{ } public DownloadEntry(string url, string savedPath, object data)
{
Url = url;
Path = savedPath;
Data = data;
}
}

SkyParallelWebClient 类:

    /// <summary>
/// 并行的 WebClient
/// </summary>
public class SkyParallelWebClient
{
ConcurrentQueue<DownloadEntry> OptionDataList = new ConcurrentQueue<DownloadEntry>(); public SkyParallelWebClient(ICollection<DownloadEntry> downloadConfigs)
{
if (downloadConfigs == null)
{
throw new ArgumentNullException("downloadConfigs");
}
foreach (var item in downloadConfigs)
{
OptionDataList.Enqueue(item);
}
} public bool TryStart(int parallelCount)
{
string errorMessage;
return TryStart(parallelCount, out errorMessage);
} public bool TryStart(int parallelCount, out string errorMessage)
{
try
{
StartCore(parallelCount);
errorMessage = null;
return true;
}
catch (Exception ex)
{
errorMessage = ex.Message;
return false;
}
} protected void StartCore(int takeCount)
{
if (OptionDataList.Count == )
{
return;
}
IList<Task> processingTasks = new List<Task>();
for (int i = ; i < takeCount; i++)
{
if (OptionDataList.Count == )
{
break;
}
DownloadEntry downloadEntry;
if (!OptionDataList.TryDequeue(out downloadEntry))
{
break;
}
var task = Task.Factory.StartNew((data) =>
{
DownloadEntry temp = data as DownloadEntry;
if (downloadEntry == null)
return;
DownloadFile(temp);
}, downloadEntry);
processingTasks.Add(task);
}
Task.WaitAll(processingTasks.ToArray());
if (OptionDataList.Count > )
{
StartCore(takeCount);
}
} private static void DownloadFile(DownloadEntry downloadEntry)
{
using (WebClient webClient = new WebClient())
{
//set this to null if there is no proxy
webClient.Proxy = null; webClient.DownloadFile(new Uri(downloadEntry.Url), downloadEntry.Path);
}
}
}

客户端测试代码:

        private void btnRunByWebClient_Click(object sender, EventArgs e)
{
WhenAllDownloading();
var ids = GetDownloadIds();
List<DownloadEntry> downloadConfigs = new List<DownloadEntry>();
Random rd = new Random();
foreach (var id in ids)
{
downloadConfigs.Add(new DownloadEntry(TaskDemo101.GetRandomUrl(rd), TaskDemo101.GetSavedFileFullName(), id));
}
ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncRunSkyParallelWebClient), downloadConfigs);
} private void AsyncRunSkyParallelWebClient(object state)
{
SkyParallelWebClient skyParallelWebClient = new SkyParallelWebClient((List<DownloadEntry>)state);
string errorMessage;
if (!skyParallelWebClient.TryStart(, out errorMessage))
{
MessageBox.Show(errorMessage);
return;
}
WhenAllDownloaded();
}

2. 效果图

由于并行后,无法统计下载进度,所以没有进度条了。注意:每一项完成后,没有日志,也就是说下面的 “编号 99 下载 True”是不会有的!

3. 总结

以上测试可以解决并行下载的任务,且体验相对来说比较好。但有一个不完美的地方,就是该任务以一定量(比如:20个)任务为一个单元,只要这个单元中有一个任务耗费了太多太多时间,即使其它 19 个任务都非常快速地完成了,也要等在那里。下篇文章,我们将再次完善它。

谢谢浏览!

一个简单的利用 WebClient 异步下载的示例(三)的更多相关文章

  1. 一个简单的利用 WebClient 异步下载的示例(二)

    继上一篇 一个简单的利用 WebClient 异步下载的示例(一) 后,我想把核心的处理提取出来,成 SkyWebClient,如下: 1. SkyWebClient 该构造函数中 downloadC ...

  2. 一个简单的利用 WebClient 异步下载的示例(一)

    继上一篇文章 一个简单的利用 HttpClient 异步下载的示例 ,我们知道不管是 HttpClient,还算 WebClient,都不建议每次调用都 new HttpClient,或 new We ...

  3. 一个简单的利用 WebClient 异步下载的示例(五)(完结篇)

    接着上一篇,我们继续来优化.我们的 SkyParallelWebClient 可否支持切换“同步下载模式”和“异步下载模式”呢,好处是大量的代码不用改,只需要调用 skyParallelWebClie ...

  4. 一个简单的利用 WebClient 异步下载的示例(四)

    接上一篇,我们继续优化它. 1. DownloadEntry 类 public class DownloadEntry { public string Url { get; set; } public ...

  5. 一个简单的利用 HttpClient 异步下载的示例

    可能你还会喜欢 一个简单的利用 WebClient 异步下载的示例  ,且代码更加新. 1. 定义自己的 HttpClient 类. using System; using System.Collec ...

  6. VC6下OpenGL 开发环境的构建外加一个简单的二维网络棋盘绘制示例

    一.安装GLUT 工具包 GLUT 不是OpenGL 所必须的,但它会给我们的学习带来一定的方便,推荐安装. Windows 环境下的GLUT 本地下载地址:glut-install.zip(大小约为 ...

  7. [.NET] 一步步打造一个简单的 MVC 电商网站 - BooksStore(三)

    一步步打造一个简单的 MVC 电商网站 - BooksStore(三) 本系列的 GitHub地址:https://github.com/liqingwen2015/Wen.BooksStore &l ...

  8. 一个简单的AXIS远程调用Web Service示例

    我们通常都将编写好的Web Service发布在Tomcat或者其他应用服务器上,然后通过浏览器调用该Web Service,返回规范的XML文件.但是如果我们不通过浏览器调用,而是通过客户端程序调用 ...

  9. [c#]WebClient异步下载文件并显示进度

    摘要 在项目开发中经常会用到下载文件,这里使用winform实现了一个带进度条的例子. 一个例子 using System; using System.Collections.Generic; usi ...

随机推荐

  1. 用 Python 监控知乎和微博的热门话题

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: TED Crossin的编程教室 PS:如有需要Python学习资料 ...

  2. Java生鲜电商平台-B2B生鲜的互联网思维

    Java生鲜电商平台-B2B生鲜的互联网思维 在互联网高速发展的今天,为我们的生活带来了众多便利.然而互联网从早期的萌芽状态到现在妇孺皆知,它的崛起速度远远超乎世人的想象.人们开始关注互联网并且研究它 ...

  3. [转]The Regular Expression Object Model

    本文转自:https://docs.microsoft.com/en-us/dotnet/standard/base-types/the-regular-expression-object-model ...

  4. 第三方库Mantle的源码解析

    Mantle是一个用于简化Cocoa或Cocoa Touch程序中model层的第三方库.通常我们的应该中都会定义大量的model来表示各种数据结构,而这些model的初始化和编码解码都需要写大量的代 ...

  5. USB通信协议深入理解

    0. 基本概念 一个[传输](控制.批量.中断.等时):由多个[事务]组成: 一个[事务](IN.OUT.SETUP):由一多个[Packet]组成. USB数据在[主机软件]与[USB设备特定的端点 ...

  6. JDBC API浅析

    使用java开发数据库应用程序一般都需要用到四个接口:Driver.Connection.Statement.ResultSet 1.Driver接口用于加载驱动程序 2.Connection接口用于 ...

  7. 第15讲:嵌入式SQL语句(动态SQL)

    一.动态SQL概述 1. 静态SQL vs 动态SQL ①动态SQL是相对静态SQL而言的 ②静态SQL特点:SQL语句在程序中已经按要求写好,只需要把一些参数通过变量传递给SQL语句即可 specN ...

  8. JS之for循环面试题

    今天同事问了道问题 ,b=; ,b<;++a,++b){ g=a+b } console.log(g) 问输出结果为多少??? 答案:12 这里要知道for循环的条件不管写多少个,必须都满足才可 ...

  9. alertmanager

    alertmanager主要用于接收prometheus发送的告警信息: wget下载,解压, 配置alertmanager.yml,内容如下: 在prometheus文件下添加rules.yml内容 ...

  10. IEEE754 浮点数

    IEEE754 浮点数 1.阅读IEEE754浮点数 A,阶码是用移码表示的,这里会有一个127的偏移量,它的127相当于0,小于127时为负,大于127时为正,比如:10000001表示指数为129 ...