继上一篇文章 一个简单的利用 HttpClient 异步下载的示例 ,我们知道不管是 HttpClient,还算 WebClient,都不建议每次调用都 new HttpClient,或 new WebClient,而应该尽量重复对象,可以把一个 WebClient(或 HttpClient)理解成一个浏览器,不能没打开一个页面以后,就销毁它,再重新创建一个,这样会有性能损失,而建议一个线程共用一个 WebClient(或 HttpClient)。这一次,我们利用 WebClient 来实现异步下载,这一次,我们增加一个进度条来显示进度。
直接提代码了:
1. TaskDemo101
优化后的 TaskDemo101 类:
public static class TaskDemo101 { public static string GetRandomUrl() { string url1 = "http://www.xxx.me/Uploads/image/20130129/2013012920080761761.jpg"; string url2 = "http://www.xxx.me/Uploads/image/20121222/20121222230686278627.jpg"; string url3 = "http://www.xxx.me/Uploads/image/20120606/20120606222018461846.jpg"; string url4 = "http://www.xxx.me/Uploads/image/20121205/20121205224383848384.jpg"; string url5 = "http://www.xxx.me/Uploads/image/20121205/20121205224251845184.jpg"; string resultUrl; int randomNum = new Random().Next(1, 6); switch (randomNum) { case 1: resultUrl = url1; break; case 2: resultUrl = url2; break; case 3: resultUrl = url3; break; case 4: resultUrl = url4; break; case 5: resultUrl = url5; break; default: throw new Exception(""); } return resultUrl; } public static string GetSavedFileFullName() { string targetFolderDestination = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "downloads\images\"); try { Directory.CreateDirectory(targetFolderDestination); } catch (Exception) { Console.WriteLine("创建文件夹失败!"); } string targetFileDestination = Path.Combine(targetFolderDestination, string.Format("img_{0}.png", DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"))); return targetFileDestination; } public static async Task<bool> RunByHttpClient(SkyHttpClient skyHttpClient, int id) { var task = skyHttpClient.DownloadImage(GetRandomUrl()); return await task.ContinueWith<bool>(t => { File.WriteAllBytes(GetSavedFileFullName(), t.Result); return true; }); } public static void RunByWebClient(WebClient webClient, int id) { webClient.DownloadFileAsync(new Uri(GetRandomUrl()), GetSavedFileFullName()); } }
2. Form1
这一次我们的 Form1 实现了 INotifyPropertyChanged 接口
public partial class Form1 : Form, INotifyPropertyChanged { #region 字段、属性 public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string prop) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(prop)); } } WebClient webc = new WebClient(); bool _canChange = true; public bool CanChange { get { return _canChange; } set { _canChange = value; OnPropertyChanged("CanChange"); } } #endregion public Form1() { InitializeComponent(); webc.DownloadFileCompleted += Webc_DownloadFileCompleted; //注册下载完成事件 webc.DownloadProgressChanged += Webc_DownloadProgressChanged; //注册下载进度改变事件 } private List<int> GetDownloadIds() { List<int> ids = new List<int>(100); for (int i = 1; i <= 100; i++) { ids.Add(i); } return ids; } private void WhenAllDownloading() { this.listBoxLog.Items.Insert(0, 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(0, string.Format("当前时间:{0},编号 {1} 下载 {2}!", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), id, singleDownloadSuccess)); } private void WhenAllDownloaded() { this.listBoxLog.Items.Insert(0, 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) { if (CanChange) { WhenAllDownloading(); CanChange = false; ToDownload.Clear(); foreach (var id in GetDownloadIds()) { ToDownload.Enqueue(id); } progressBar1.Maximum = ToDownload.Count * 100; btnRunByWebClient.Text = "用 WebClient 暂停下载"; int firstId = ToDownload.Dequeue(); TaskDemo101.RunByWebClient(webc, firstId); WhenSingleDownloaded(firstId, true); } else { ToDownload.Clear(); webc.CancelAsync(); CanChange = true; progressBar1.Value = 0; btnRunByWebClient.Text = "用 WebClient 开始下载"; } } private void Webc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { if (e.Error != null && !e.Cancelled) { MessageBox.Show("下载时出现错误: " + e.Error.Message); CanChange = true; progressBar1.Value = 0; } else { DownloadNext(); } } private void Webc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { progressBar1.Value = progressBar1.Maximum - ((ToDownload.Count + 1) * 100) + e.ProgressPercentage; } Queue<int> ToDownload = new Queue<int>(); private void DownloadNext() { if (ToDownload.Any()) { int nextId = ToDownload.Dequeue(); TaskDemo101.RunByWebClient(webc, nextId); WhenSingleDownloaded(nextId, true); progressBar1.Value = progressBar1.Maximum - ((ToDownload.Count + 1) * 100); } else { MessageBox.Show("全部下载完成"); CanChange = true; progressBar1.Value = 0; btnRunByWebClient.Text = "用 WebClient 开始下载"; WhenAllDownloaded(); } } }
3. 运行截图
如图:
下载完成以后:
谢谢浏览!