继续上一篇 一个简单的利用 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. 【51Nod1769】Clarke and math2(数论,组合数学)

    [51Nod1769]Clarke and math2(数论,组合数学) 题面 51Nod 题解 考虑枚举一个\(i_k\),枚举一个\(i\),怎么计算\(i_k\)对\(i\)的贡献. 把\(\f ...

  2. kfifo

    kfifo 的一些伪代码 kfifo_len() out = LOAD fifo->out smp_rmb() len = LOAD fifo->in - out kfifo_in() k ...

  3. Socket,Tcp,Http的关联

    下面的图表试图显示不同的TCP/IP和其他的协议在最初OSI模型中的位置: TCP/IP 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议 ...

  4. JDK1.8新特性——使用新的方式遍历集合

    JDK1.8新特性——使用新的方式遍历集合 摘要:本文主要学习了在JDK1.8中新增的遍历集合的方式. 遍历List 方法: default void forEach(Consumer<? su ...

  5. Initialize a Property After Creating an Object创建对象后初始化属性 即如何设置对象的默认值(EF)

    In this lesson, you will learn how to set the default value for a particular property of a business ...

  6. HashMap、ConcurrentHashMap解析

    一.HashMap分析 在JDK1.8之前,hashMap由数组+链表组成,1.8之后,对hashMap进行了一些修改,最大的不同就是利用了红黑树,所以其由数组+链表+红黑树组成.查找时,根据hash ...

  7. Web基础--JavaScript入门

    一.JavaScript 1.什么是JavaScript(JS) (1)JavaScript是嵌入HTML中的代码,在浏览器中执行的脚本语言,具有与Java和C语言类似的语法.(2)一种网页编程技术, ...

  8. 每天一点产品思考(5):Web端链接跳转在当前页面刷新还是新标签页打开?

    一.与交互设计师的突然撕逼         今天阿白在验收产品的时候,在博客首页打开一篇博文,是在原先的页面进行刷新,而不是新开一个标签页打开.阿白让开发改成在新标签页中打开,但是开发说这是设计师设计 ...

  9. redis删除策略

    redis 设置过期时间 Redis 中有个设置时间过期的功能,即对存储在 redis 数据库中的值可以设置一个过期时间.作为一个缓存数据库,这是非常实用的.如我们一般项目中的 token 或者一些登 ...

  10. C学习笔记(10)--- 强制类型转换,错误处理,递归

    1.强制类型转换: 强制类型转换是把变量从一种类型转换为另一种数据类型.例如,如果您想存储一个 long 类型的值到一个简单的整型中,您需要把 long 类型强制转换为 int 类型. 您可以使用强制 ...