一个简单的利用 WebClient 异步下载的示例(二)
继上一篇 一个简单的利用 WebClient 异步下载的示例(一) 后,我想把核心的处理提取出来,成 SkyWebClient,如下:
1. SkyWebClient
该构造函数中 downloadConfigs 参数是必须的,不能为 NULL,而 ProgressBar progressBar 可为空,只不过不能显示进度条而已。
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;
}
} /// <summary>
/// 当单个下载前的事件处理
/// </summary>
/// <param name="current">当前处理的数据,有可能为 NULL,请注意判断</param>
public delegate void WhenSingleDownloadingEventHandler(DownloadEntry current); /// <summary>
/// 当全部下载完毕后的事件处理
/// </summary>
public delegate void WhenAllDownloadedEventHandler(); /// <summary>
/// 当下载错误时
/// </summary>
/// <param name="ex"></param>
public delegate void WhenDownloadingErrorEventHandler(Exception ex); public class SkyWebClient : INotifyPropertyChanged
{
#region 字段、属性 public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string prop)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
} /// <summary>
/// 当单个下载前的事件处理
/// </summary>
public event WhenSingleDownloadingEventHandler WhenSingleDownloading;
private void OnWhenSingleDownloading(DownloadEntry next)
{
if (WhenSingleDownloading != null)
{
WhenSingleDownloading(next);
}
} /// <summary>
/// 当全部下载完毕后的事件处理
/// </summary>
public event WhenAllDownloadedEventHandler WhenAllDownloaded;
private void OnWhenAllDownloaded()
{
if (WhenAllDownloaded != null)
{
WhenAllDownloaded();
}
} /// <summary>
/// 当全部下载完毕后的事件处理
/// </summary>
public event WhenDownloadingErrorEventHandler WhenDownloadingError;
private void OnWhenDownloadingError(Exception ex)
{
if (WhenDownloadingError != null)
{
WhenDownloadingError(ex);
}
} ProgressBar progressBar;
WebClient webc;
Queue<DownloadEntry> ToDownload = new Queue<DownloadEntry>(); bool _canChange = true;
public bool CanChange
{
get
{
return _canChange;
}
set
{
_canChange = value;
OnPropertyChanged("CanChange");
}
} #endregion public SkyWebClient(IEnumerable<DownloadEntry> downloadConfigs)
:this(downloadConfigs, null)
{ } public SkyWebClient(IEnumerable<DownloadEntry> downloadConfigs, ProgressBar progressBar)
{
if (downloadConfigs == null)
{
throw new ArgumentNullException("downloadConfigs");
}
foreach (DownloadEntry item in downloadConfigs)
{
ToDownload.Enqueue(item);
}
this.webc = new WebClient();
this.progressBar = progressBar; webc.DownloadFileCompleted += Webc_DownloadFileCompleted; //注册下载完成事件
webc.DownloadProgressChanged += Webc_DownloadProgressChanged; //注册下载进度改变事件
} public void Start()
{
if (ToDownload.Count == )
{
Downloaded();
return;
}
if (CanChange)
{
CanChange = false;
if (this.progressBar != null)
{
this.progressBar.Maximum = ToDownload.Count * ;
}
StartCore();
}
else
{
ToDownload.Clear();
webc.CancelAsync();
CanChange = true;
//this.progressBar.Value = 0;
//btnRunByWebClient.Text = "用 WebClient 开始下载";
}
} private void StartCore()
{
DownloadEntry next = ToDownload.Dequeue();
webc.DownloadFileAsync(new Uri(next.Url), next.Path);
OnWhenSingleDownloading(next);
} private void DownloadNext()
{
if (ToDownload.Any())
{
StartCore();
if (this.progressBar != null)
{
this.progressBar.Value = this.progressBar.Maximum - ((ToDownload.Count + ) * );
}
}
else
{
if (this.progressBar != null)
{
this.progressBar.Value = ;
}
Downloaded();
}
} private void Downloaded()
{
CanChange = true;
OnWhenAllDownloaded();
} private void Webc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null && !e.Cancelled)
{
OnWhenDownloadingError(e.Error);
CanChange = true;
//this.progressBar.Value = 0;
}
else
{
DownloadNext();
}
} private void Webc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
if (this.progressBar != null)
{
this.progressBar.Value = this.progressBar.Maximum - ((ToDownload.Count + ) * ) + e.ProgressPercentage;
}
}
}
2. Form1.cs
在点击事件中,调用 SkyWebClient。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} private List<int> GetDownloadIds()
{
List<int> ids = new List<int>();
for (int i = ; i <= ; i++)
{
ids.Add(i);
}
return ids;
} private void WhenAllDownloading()
{
this.listBoxLog.Items.Insert(, string.Format("当前时间:{0},准备开始下载...", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
//禁用按钮
EnableOrDisableButtons(false);
} private void EnableOrDisableButtons(bool enabled)
{
this.btnRunByHttpClient.Enabled = enabled;
this.btnRunByWebClient.Enabled = enabled;
} private void WhenSingleDownloaded(int id, bool singleDownloadSuccess)
{
this.listBoxLog.Items.Insert(, string.Format("当前时间:{0},编号 {1} 下载 {2}!", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), id, singleDownloadSuccess));
} private void WhenAllDownloaded()
{
this.listBoxLog.Items.Insert(, string.Format("当前时间:{0},下载完毕!", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
//启用按钮
EnableOrDisableButtons(true);
} private async void btnRunByHttpClient_Click(object sender, EventArgs e)
{
SkyHttpClient skyHttpClient = new SkyHttpClient();
try
{
WhenAllDownloading();
foreach (var id in GetDownloadIds())
{
bool singleDownloadSuccess = await TaskDemo101.RunByHttpClient(skyHttpClient, id);
WhenSingleDownloaded(id, singleDownloadSuccess);
}
WhenAllDownloaded();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Download Error!");
}
} 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));
}
SkyWebClient skyWebClient = new SkyWebClient(downloadConfigs, this.progressBar1);
skyWebClient.WhenAllDownloaded += SkyWebClient_WhenAllDownloaded;
skyWebClient.WhenSingleDownloading += SkyWebClient_WhenSingleDownloading;
skyWebClient.WhenDownloadingError += SkyWebClient_WhenDownloadingError;
skyWebClient.Start();
} private void SkyWebClient_WhenDownloadingError(Exception ex)
{
MessageBox.Show("下载时出现错误: " + ex.Message);
} private void SkyWebClient_WhenSingleDownloading(DownloadEntry current)
{
WhenSingleDownloaded((int)current.Data, true);
} private void SkyWebClient_WhenAllDownloaded()
{
btnRunByWebClient.Text = "用 WebClient 开始下载";
WhenAllDownloaded();
} }
3. 运行截图
如图:

4. 总结
由于本下载采用依次来异步下载,虽然可以保证下载的文件的完整,但单位时间内效率不高,可能进度缓慢。且如果其中一个占用了较多的时间(比如:2分钟),那么整体的下载进度就会变慢。接下来,我会逐步优化它,敬请关注!
谢谢浏览!
一个简单的利用 WebClient 异步下载的示例(二)的更多相关文章
- 一个简单的利用 WebClient 异步下载的示例(三)
继续上一篇 一个简单的利用 WebClient 异步下载的示例(二) 后,继续优化它. 1. 直接贴代码了: DownloadEntry: public class DownloadEntry { p ...
- 一个简单的利用 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 ...
- [.NET] 一步步打造一个简单的 MVC 电商网站 - BooksStore(二)
一步步打造一个简单的 MVC 电商网站 - BooksStore(二) 本系列的 GitHub地址:https://github.com/liqingwen2015/Wen.BooksStore 前: ...
- 一个简单的AXIS远程调用Web Service示例
我们通常都将编写好的Web Service发布在Tomcat或者其他应用服务器上,然后通过浏览器调用该Web Service,返回规范的XML文件.但是如果我们不通过浏览器调用,而是通过客户端程序调用 ...
- [c#]WebClient异步下载文件并显示进度
摘要 在项目开发中经常会用到下载文件,这里使用winform实现了一个带进度条的例子. 一个例子 using System; using System.Collections.Generic; usi ...
- WebClient异步下载文件
namespace ConsoleAppSyncDownload{ class Program { static void Main(string[] args) { ...
随机推荐
- 遍历json数据的几种方式
json(JavaScript Object Notation),json是一种多用于存储和交换文本信息的语法.他能够进行数据的传输,通常和ajax一起使用.它具有体积小.速度快,易解析等诸多优点. ...
- ABAP 7.4 新语法-内嵌生命和内表操作(转)
转自:https://www.cnblogs.com/mingdashu/p/6744637.html ABAP 7.4 新语法-内嵌生命和内表操作 1.内嵌声明 2.内表操作 3.opensql ...
- 点击事件的坐标计算(client || offset) +(X || Width || Left) 各种排列组合别绕晕
结论: 1,X,Y的都是属于点击位置的,width.height.left.top都是属于DOM的. 2,涉及的所有位置只与document或DOM内部有关,与DOM如何定位,周围有没有其他占位HTM ...
- Sublime设置格式化代码快捷键ctrl+shift+r
1.以管理员身份运行sublime 2.首选项---按键绑定-用户,将以下代码复制即可(这里注意不要忘记在最后一行添加逗号哦) { "keys": ["ctrl+shif ...
- postgreSQL数据库的初探
kali是黑客的强大武器,还有一个也是哦——Metasploit postgreSQL数据库是Metasploit的默认数据库哦! 启动postgresql: service postgresql s ...
- SAP MM MB5L 报表里的差异金额如何调整?
SAP MM MB5L 报表里的差异金额如何调整? 5月3号,收到财务顾问提出的一个问题,说是MB5L报表里有差异. 如下查询条件, 报表结果里显示有差异, 经查,导致这个差异的原因之一是,一些物料批 ...
- curl ftp libcurl 功能使用
struct FtpFile { const char *filename; FILE *stream; }; static size_t my_fwrite(void *buffer, size_t ...
- [20190524]浅谈模糊查询.txt
[20190524]浅谈模糊查询.txt --//一台生产系统遇到监听进程莫名down的情况,3月份曾经遇到的情况,链接:http://blog.itpub.net/267265/viewspace- ...
- 使用vs code编写Markdown文档以及markdown语法详解
首先安装vscode工具,下载地址如下: https://code.visualstudio.com/ 在vs code的扩展中安装: Markdown Preview Enhanced 这款插件,安 ...
- 关于APICloud与DCloud的我的一些看法
最近因为项目需要,研究了一下市场较为流行的四种移动开发平台:Wex5.APPcan.Dcloud.APICloud,Wex5因为界面UI较为老旧,且语法和js有较大出入,APPcan不开源等缘故,主要 ...