线程机制(避免卡屏),异步下载文件。
我做网站的监控,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让其立即终断下载,还是有点深度)