一个简单的利用 WebClient 异步下载的示例(三)
继续上一篇 一个简单的利用 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 异步下载的示例(三)的更多相关文章
- 一个简单的利用 WebClient 异步下载的示例(二)
继上一篇 一个简单的利用 WebClient 异步下载的示例(一) 后,我想把核心的处理提取出来,成 SkyWebClient,如下: 1. SkyWebClient 该构造函数中 downloadC ...
- 一个简单的利用 WebClient 异步下载的示例(一)
继上一篇文章 一个简单的利用 HttpClient 异步下载的示例 ,我们知道不管是 HttpClient,还算 WebClient,都不建议每次调用都 new HttpClient,或 new We ...
- 一个简单的利用 WebClient 异步下载的示例(五)(完结篇)
接着上一篇,我们继续来优化.我们的 SkyParallelWebClient 可否支持切换“同步下载模式”和“异步下载模式”呢,好处是大量的代码不用改,只需要调用 skyParallelWebClie ...
- 一个简单的利用 WebClient 异步下载的示例(四)
接上一篇,我们继续优化它. 1. DownloadEntry 类 public class DownloadEntry { public string Url { get; set; } public ...
- 一个简单的利用 HttpClient 异步下载的示例
可能你还会喜欢 一个简单的利用 WebClient 异步下载的示例 ,且代码更加新. 1. 定义自己的 HttpClient 类. using System; using System.Collec ...
- VC6下OpenGL 开发环境的构建外加一个简单的二维网络棋盘绘制示例
一.安装GLUT 工具包 GLUT 不是OpenGL 所必须的,但它会给我们的学习带来一定的方便,推荐安装. Windows 环境下的GLUT 本地下载地址:glut-install.zip(大小约为 ...
- [.NET] 一步步打造一个简单的 MVC 电商网站 - BooksStore(三)
一步步打造一个简单的 MVC 电商网站 - BooksStore(三) 本系列的 GitHub地址:https://github.com/liqingwen2015/Wen.BooksStore &l ...
- 一个简单的AXIS远程调用Web Service示例
我们通常都将编写好的Web Service发布在Tomcat或者其他应用服务器上,然后通过浏览器调用该Web Service,返回规范的XML文件.但是如果我们不通过浏览器调用,而是通过客户端程序调用 ...
- [c#]WebClient异步下载文件并显示进度
摘要 在项目开发中经常会用到下载文件,这里使用winform实现了一个带进度条的例子. 一个例子 using System; using System.Collections.Generic; usi ...
随机推荐
- MSSQL查询当前登录进程以及执行状态
--当前连接进程declare @tempTable table (SPID INT,Status VARCHAR(255), Login VARCHAR(255),HostName VARCHAR( ...
- .NET MVC5简介(六)HttpHandler
浏览器到网站程序 上一篇中,介绍IHttpModule的时候,自定义一个类CustomHttpModule继承自IHttpModule,自定义一个事件,并配合配置文件,就可以执行自定义Module中的 ...
- 用 Python 监控知乎和微博的热门话题
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: TED Crossin的编程教室 PS:如有需要Python学习资料 ...
- 怎样深入学习php,成为php高手!?
本文章开头我想问一句话:PHP是做什么的? 因为这是面试中会问到的一个问题,虽然它看起来很简单,回答做网站的,也就是个简单建站的水平.回答做网站后端开发的,对PHP有了一定的认识,回答做后端处理的,有 ...
- java核心技术第五篇之事务和MVC模式
第一部分:事务1.事务的简介: 1.1 在一组操作中(比如增加操作,修改操作),只有增加和修改操作都成功之后,这两个操作才能真正的成功. ,如果这两个操作中,有一个失败了,这两个操作都失败了. 1.2 ...
- springcloud vue 微服务分布式 activiti工作流 前后分离 集成代码生成器 shiro权限
1.代码生成器: [正反双向](单表.主表.明细表.树形表,快速开发利器)freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本.处理类.service等完整模块2. ...
- arcgis api for javascript 学习(六) 地图打印
1.本文应用arcgis api for javascript对发布的动态地图进行打印,打印的为PDF格式,打印出来如图: 2.需要特别注意的是:我们在运行代码前,需要打开PrintingTools, ...
- SRDC - ORA-22924 or ORA-1555 on LOB data: Checklist of Evidence to Supply (Doc ID 1682707.1)
SRDC - ORA-22924 or ORA-1555 on LOB data: Checklist of Evidence to Supply (Doc ID 1682707.1) Action ...
- web网页利用JavaScript实现对摄像头的调用
实现效果: 代码如下: <!DOCTYPE html> <html lang="zh"> <head> <meta charset=&qu ...
- python爬虫(3)——用户和IP代理池、抓包分析、异步请求数据、腾讯视频评论爬虫
用户代理池 用户代理池就是将不同的用户代理组建成为一个池子,随后随机调用. 作用:每次访问代表使用的浏览器不一样 import urllib.request import re import rand ...