WebClient.DownloadFile(线程机制,异步下载文件)

简介:

线程机制(避免卡屏),异步下载文件。

  我做网站的监控,WebClient.DownloadFile这个方法是我经常用到的,必要的时候肯定是要从网上下载些什么(WebRequest 也可以下载网络文件,不妨搜下,不过WebClient.DownloadFile使用更简单)。

 

  今天简单的演示下WebClient.DownloadFileAsync的使用,刚刚写好的实例,有问题你拍我。

  解释什么的都不需要了吧。这里面应用了线程机制,异步调用。wo先展示代码,在把一些关键点放置到后面,并给一些修改建议(设计器生成代码在下,可以不用看,只需要复制粘贴使用)。

测试中用到的网络文件(随机抽取.exe,.rar,.zip),都是无害的,请放心测试:

http://dl1sw.baidu.com/client/9h162/fzjqd.exe
http://sq.onlinedown.net/down/sgbs.rar
http://zj.down.chinaz.com/201408/bdswxt_v1.0.zip
http://zj.down.chinaz.com/201408/zyzfwxt_v1.1.zip

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
using  System;
using  System.Collections.Generic;
using  System.ComponentModel;
using  System.Data;
using  System.Drawing;
using  System.Linq;
using  System.Text;
using  System.Windows.Forms;
using  System.Net;
using  System.Threading;
using  System.IO;
namespace  WindowsFormsApplication1
{
     public  partial  class  Form1 : Form
     {
         public  Form1()
         {
             InitializeComponent();
             AppDomain.CurrentDomain.UnhandledException +=  new  UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
         }
         static  void  CurrentDomain_UnhandledException( object  sender, UnhandledExceptionEventArgs e)
         {
             File.AppendAllText(AppDomain.CurrentDomain.BaseDirectory +  "error.log" , DateTime.Now.ToString() +  "\t"  + e.ExceptionObject.ToString() + Environment.NewLine);
         }
         /// <summary>
         /// 文件总数
         /// </summary>
         int  _totalFile = 0;
         /// <summary>
         /// 已下载文件
         /// </summary>
         int  _loadFile = 0;
         private  void  button1_Click( object  sender, EventArgs e)
         { //Run
             string  richText = richTextBox1.Text;
             if  ( string .IsNullOrEmpty(richText))
             {
                 MessageBox.Show( "请在文本框中输入需要下载的网络文件" );
             }
             Thread thread =  new  Thread( new  ThreadStart(() => createWebClient(richText)));
             thread.Start();
         }
         //WebClient webClient = null;
         private  void  createWebClient( string  richText)
         {
             string [] array = richText.Split( new  string [] {  "\r" "\n"  }, StringSplitOptions.RemoveEmptyEntries);
             _totalFile = array.Length;
             foreach  ( string  item  in  array)
             {
                 WebClient webClient =  new  WebClient();
                 webClient.DownloadProgressChanged +=  new  DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
                 webClient.DownloadFileCompleted +=  new  AsyncCompletedEventHandler(webClient_DownloadFileCompleted);
                 string  fileName = AppDomain.CurrentDomain.BaseDirectory + DateTime.Now.ToFileTimeUtc() + item.Substring(item.LastIndexOf( '/' ) + 1);
                 webClient.DownloadFileAsync( new  Uri(item), fileName);
             }
         }
         private  void  webClient_DownloadProgressChanged( object  sender, DownloadProgressChangedEventArgs e)
         {
             this .Invoke( new  MethodInvoker( delegate  {
                 this .progressBar2.Value = e.ProgressPercentage;
                 this .label2.Text =  string .Format( "正在下载文件,完成进度{0}%  {1}/{2}(字节)"
                                     ,e.ProgressPercentage
                                     , e.BytesReceived
                                     , e.TotalBytesToReceive);
              }));
         }
         private  void  webClient_DownloadFileCompleted( object  sender, AsyncCompletedEventArgs e)
         {
             _loadFile++;
             int  percent = ( int )(100.0 * _loadFile / _totalFile);
             this .Invoke( new  MethodInvoker( delegate  {
                 this .progressBar1.Value = percent;
                 this .label1.Text =  string .Format( "已完成文件下载{0}%  {1}/{2}(文件个数)"
                     , percent
                     , _loadFile
                     , _totalFile);
             }));
             if  (sender  is  WebClient)
             {
                 ((WebClient)sender).CancelAsync();
                 ((WebClient)sender).Dispose();
             }
         }
         private  System.ComponentModel.IContainer components =  null ;
         protected  override  void  Dispose( bool  disposing)
         {
             if  (disposing && (components !=  null ))
             {
                 components.Dispose();
             }
             base .Dispose(disposing);
         }
         private  void  InitializeComponent()
         {
             this .progressBar1 =  new  System.Windows.Forms.ProgressBar();
             this .progressBar2 =  new  System.Windows.Forms.ProgressBar();
             this .label1 =  new  System.Windows.Forms.Label();
             this .label2 =  new  System.Windows.Forms.Label();
             this .label3 =  new  System.Windows.Forms.Label();
             this .label4 =  new  System.Windows.Forms.Label();
             this .richTextBox1 =  new  System.Windows.Forms.RichTextBox();
             this .button1 =  new  System.Windows.Forms.Button();
             this .SuspendLayout();
             // 
             // progressBar1
             // 
             this .progressBar1.Location =  new  System.Drawing.Point(81, 160);
             this .progressBar1.Name =  "progressBar1" ;
             this .progressBar1.Size =  new  System.Drawing.Size(330, 12);
             this .progressBar1.TabIndex = 0;
             // 
             // progressBar2
             // 
             this .progressBar2.Location =  new  System.Drawing.Point(81, 224);
             this .progressBar2.Name =  "progressBar2" ;
             this .progressBar2.Size =  new  System.Drawing.Size(330, 12);
             this .progressBar2.TabIndex = 1;
             // 
             // label1
             // 
             this .label1.AutoSize =  true ;
             this .label1.Location =  new  System.Drawing.Point(59, 187);
             this .label1.Name =  "label1" ;
             this .label1.Size =  new  System.Drawing.Size(41, 12);
             this .label1.TabIndex = 2;
             this .label1.Text =  "label1" ;
             // 
             // label2
             // 
             this .label2.AutoSize =  true ;
             this .label2.Location =  new  System.Drawing.Point(59, 252);
             this .label2.Name =  "label2" ;
             this .label2.Size =  new  System.Drawing.Size(41, 12);
             this .label2.TabIndex = 3;
             this .label2.Text =  "label2" ;
             // 
             // label3
             // 
             this .label3.AutoSize =  true ;
             this .label3.Location =  new  System.Drawing.Point(12, 160);
             this .label3.Name =  "label3" ;
             this .label3.Size =  new  System.Drawing.Size(65, 12);
             this .label3.TabIndex = 4;
             this .label3.Text =  "总 进 度:" ;
             // 
             // label4
             // 
             this .label4.AutoSize =  true ;
             this .label4.Location =  new  System.Drawing.Point(12, 224);
             this .label4.Name =  "label4" ;
             this .label4.Size =  new  System.Drawing.Size(65, 12);
             this .label4.TabIndex = 5;
             this .label4.Text =  "当前进度:" ;
             // 
             // richTextBox1
             // 
             this .richTextBox1.Location =  new  System.Drawing.Point(14, 12);
             this .richTextBox1.Name =  "richTextBox1" ;
             this .richTextBox1.Size =  new  System.Drawing.Size(397, 131);
             this .richTextBox1.TabIndex = 6;
             this .richTextBox1.Text =  "" ;
             // 
             // button1
             // 
             this .button1.Location =  new  System.Drawing.Point(150, 280);
             this .button1.Name =  "button1" ;
             this .button1.Size =  new  System.Drawing.Size(75, 23);
             this .button1.TabIndex = 7;
             this .button1.Text =  "Run" ;
             this .button1.UseVisualStyleBackColor =  true ;
             this .button1.Click +=  new  System.EventHandler( this .button1_Click);
             // 
             // Form1
             // 
             this .AutoScaleDimensions =  new  System.Drawing.SizeF(6F, 12F);
             this .AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
             this .ClientSize =  new  System.Drawing.Size(423, 315);
             this .Controls.Add( this .button1);
             this .Controls.Add( this .richTextBox1);
             this .Controls.Add( this .label4);
             this .Controls.Add( this .label3);
             this .Controls.Add( this .label2);
             this .Controls.Add( this .label1);
             this .Controls.Add( this .progressBar2);
             this .Controls.Add( this .progressBar1);
             this .MaximumSize =  new  System.Drawing.Size(439, 353);
             this .MinimumSize =  new  System.Drawing.Size(439, 353);
             this .Name =  "Form1" ;
             this .Text =  "WebClient下载实现实例" ;
             this .ResumeLayout( false );
             this .PerformLayout();
         }
         private  System.Windows.Forms.ProgressBar progressBar1;
         private  System.Windows.Forms.ProgressBar progressBar2;
         private  System.Windows.Forms.Label label1;
         private  System.Windows.Forms.Label label2;
         private  System.Windows.Forms.Label label3;
         private  System.Windows.Forms.Label label4;
         private  System.Windows.Forms.RichTextBox richTextBox1;
         private  System.Windows.Forms.Button button1;
     }
}

 

大致看了一下,貌似就以下几句需要新手斟酌,大神请绕行。

第一句: this.Invoke(new MethodInvoker(delegate {

第二句:Thread thread = new Thread(new ThreadStart(() => createWebClient(richText)));

第三句:if (sender is WebClient)

 

第一句是关键的一句,不再创建控件的线程中调用/修改控件的属性值(Text),会报异常,为什么这么用就OK了?

第二句,第三句就简单了,不提示了,不会了找度度。

 

本程序可以添加的功能,添加一个Stop按钮,终断下载(请不要嗤之以鼻,在创建窗体的线程里操作new Thread让其立即终断下载,还是有点深度)










本文转自 yuanzhitang 51CTO博客,原文链接:http://blog.51cto.com/yuanzhitang/1949842,如需转载请自行联系原作者
目录
相关文章
|
10月前
|
数据采集 Java API
Jsoup库能处理多线程下载吗?
Jsoup库能处理多线程下载吗?
|
28天前
|
开发者 Windows
NDM多线程下载器!实用的下载器,绿色版下载及安装教程
NDM是一款小巧高效的多线程下载器,支持Windows、Mac及浏览器插件,绿色单文件仅904KB,无需安装。已汉化,操作简单,下载速度快,支持HTTP/HTTPS/FTP协议,不支持磁力链接。使用前需关闭杀毒软件,配合7-ZIP解压,浏览器插件可自动嗅探音视频资源。
187 2
|
3月前
|
数据采集 存储 JSON
Python爬取知乎评论:多线程与异步爬虫的性能优化
Python爬取知乎评论:多线程与异步爬虫的性能优化
|
3月前
|
数据采集 监控 调度
干货分享“用 多线程 爬取数据”:单线程 + 协程的效率反超 3 倍,这才是 Python 异步的正确打开方式
在 Python 爬虫中,多线程因 GIL 和切换开销效率低下,而协程通过用户态调度实现高并发,大幅提升爬取效率。本文详解协程原理、实战对比多线程性能,并提供最佳实践,助你掌握异步爬虫核心技术。
|
编解码 数据安全/隐私保护 计算机视觉
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
如何使用OpenCV进行同步和异步操作来打开海康摄像头,并提供了相关的代码示例。
733 1
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
|
9月前
|
并行计算 安全 Java
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
在Python开发中,GIL(全局解释器锁)一直备受关注。本文基于CPython解释器,探讨GIL的技术本质及其对程序性能的影响。GIL确保同一时刻只有一个线程执行代码,以保护内存管理的安全性,但也限制了多线程并行计算的效率。文章分析了GIL的必要性、局限性,并介绍了多进程、异步编程等替代方案。尽管Python 3.13计划移除GIL,但该特性至少要到2028年才会默认禁用,因此理解GIL仍至关重要。
604 16
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
|
8月前
|
缓存 安全 Java
面试中的难题:线程异步执行后如何共享数据?
本文通过一个面试故事,详细讲解了Java中线程内部开启异步操作后如何安全地共享数据。介绍了异步操作的基本概念及常见实现方式(如CompletableFuture、ExecutorService),并重点探讨了volatile关键字、CountDownLatch和CompletableFuture等工具在线程间数据共享中的应用,帮助读者理解线程安全和内存可见性问题。通过这些方法,可以有效解决多线程环境下的数据共享挑战,提升编程效率和代码健壮性。
274 6
|
数据采集 XML JavaScript
C# 中 ScrapySharp 的多线程下载策略
C# 中 ScrapySharp 的多线程下载策略
|
9月前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
351 17
|
11月前
|
存储 监控 安全
深入理解ThreadLocal:线程局部变量的机制与应用
在Java的多线程编程中,`ThreadLocal`变量提供了一种线程安全的解决方案,允许每个线程拥有自己的变量副本,从而避免了线程间的数据竞争。本文将深入探讨`ThreadLocal`的工作原理、使用方法以及在实际开发中的应用场景。
242 2

热门文章

最新文章