BackgroundWorker是微软的在.net Framwork中添加的一个组件,主要对线程的访问提供了一种安全的方式。简单的说就是对Thread的一次封装。
BackgroundWorker位于System.ComponentModel下,是一个继承了Component的组件,微软官方的解释为:Executes an operation on a separate thread.就是说,开始一个新的线程执行操作。
首先介绍一下BackgroundWorker的相关属性和方法:
属性:
WorkerReportsProgress:是否可以报告进度。
WorkerSupportsCancellation:是否允许异步中止。
IsBusy:是否在运行。
CancellationPending:判断BackgroundWorker是否已经异步取消。
方法:
RunWorkerAsync:开始执行任务。触发DoWork事件
ReportProgress:异步提醒,触发ProgressChanged事件,但是这个如果可以使用,必须设置WorkerReportsProgress为True
CancelAsync:取消BackgroundWorker操作。
事件:
DoWork:执行RunWorkerAsync后触发,异步执行的认为。
ProgressChanged:执行ReportProgress时触发,异步获得进度。
RunWorkerCompleted:线程结束时触发,主要有成功结束,发生异常或者取消时发生。
Thread相对来说就简单了,但是使用起来就比较麻烦了。Thread位于System.Threading的名空间下,是一个可以独立创建和操作一个线程,并且对线程进行设置优先级和获得状态的一个不可继承的类。
下面是我做的一个例子,来比较他们两个的使用。
建立一个窗体,放置了两个TextBox,分别为设置开始和结束的Progree的值,放置两个ProgressBar,分别设置为线程的Progressbar和BackGroundWorker的ProgressBar。另外放置按钮为StartBackGroundWorker,StartThread,CancelBackGroundWorker,CancelThread和PauseThread。
BackGroundWorker的使用就非常简单:
1
///
<summary>
2
///
Handles the Click event of the btnBackGroundWorker control.
3
///
</summary>
4
///
<param name="sender">
The source of the event.
</param>
5
///
<param name="e">
The
<see cref="System.EventArgs"/>
instance containing the event data.
</param>
6
private
void
btnBackGroundWorker_Click(
object
sender, EventArgs e)
7
{
8
StartFrom
=
Convert.ToInt32(txtStart.Text);
9
EndTo
=
Convert.ToInt32(txtEnd.Text);
10
11
progressBarThread.Minimum
=
StartFrom;
12
progressBarThread.Maximum
=
EndTo;
13
14
this
.btnBackGroundWorker.Enabled
=
false
;
15
16
this
.backgroundWorker.RunWorkerAsync();
17
}
18
19
///
<summary>
20
///
Handles the DoWork event of the backgroundWorker control.
21
///
</summary>
22
///
<param name="sender">
The source of the event.
</param>
23
///
<param name="e">
The
<see cref="System.ComponentModel.DoWorkEventArgs"/>
instance containing the event data.
</param>
24
private
void
backgroundWorker_DoWork(
object
sender, DoWorkEventArgs e)
25
{
26
for
(
int
nValue
=
StartFrom; nValue
<=
EndTo; nValue
++
)
27
{
28
if
(
this
.backgroundWorker.CancellationPending)
29
{
30
e.Cancel
=
true
;
31
return
;
32
}
33
this
.backgroundWorker.ReportProgress(nValue);
34
Thread.Sleep(
200
);
35
}
36
}
37
38
///
<summary>
39
///
Handles the ProgressChanged event of the backgroundWorker control.
40
///
</summary>
41
///
<param name="sender">
The source of the event.
</param>
42
///
<param name="e">
The
<see cref="System.ComponentModel.ProgressChangedEventArgs"/>
instance containing the event data.
</param>
43
private
void
backgroundWorker_ProgressChanged(
object
sender, ProgressChangedEventArgs e)
44
{
45
this
.prgProcessBackGroundWorker.Value
=
e.ProgressPercentage;
46
}
47
48
///
<summary>
49
///
Handles the RunWorkerCompleted event of the backgroundWorker control.
50
///
</summary>
51
///
<param name="sender">
The source of the event.
</param>
52
///
<param name="e">
The
<see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/>
instance containing the event data.
</param>
53
private
void
backgroundWorker_RunWorkerCompleted(
object
sender, RunWorkerCompletedEventArgs e)
54
{
55
//
取消
56
if
(e.Cancelled)
57
{
58
MessageBox.Show(
"
Cancelled
"
);
59
}
60
//
出现错误
61
else
if
(e.Error
!=
null
)
62
{
63
MessageBox.Show(e.Error.Message
+
Environment.NewLine
+
e.Error.StackTrace);
64
}
65
//
完成
66
else
67
{
68
MessageBox.Show(
"
Completed
"
);
69
this
.btnBackGroundWorker.Enabled
=
true
;
70
}
71
}
72
73
///
<summary>
74
///
Handles the Click event of the btnCancelBackgroundWoker control.
75
///
</summary>
76
///
<param name="sender">
The source of the event.
</param>
77
///
<param name="e">
The
<see cref="System.EventArgs"/>
instance containing the event data.
</param>
78
private
void
btnCancelBackgroundWoker_Click(
object
sender, EventArgs e)
79
{
80
this
.backgroundWorker.CancelAsync();
81
}
Thread的使用就比较麻烦了,对于尤其是对异步提醒来说,需要写委托,代码量是很多,但是对于BackgroundWorker来说,却没有线程暂停和继续的方法。但是对于一般的来说,这些功能也是不用的,而且在微软的文档中还提到了,Thread的Resume和Suspend已经不推荐使用。
1
//
声明委托
2
delegate
void
DelegateType(
int
x);
3
DelegateType TheDelegate;
4
5
//
ProgressBar的开始和结束值
6
int
StartFrom, EndTo;
7
8
//
是否线程暂停
9
bool
IsThreadPaused;
10
11
ManualResetEvent CancelEvent
=
new
ManualResetEvent(
false
);
12
Thread MyThread;
13
14
///
<summary>
15
///
委托的消息事件
16
///
</summary>
17
///
<param name="nProgress">
进度值
</param>
18
private
void
MessageHandler(
int
nProgress)
19
{
20
lblThreadStatus.Text
=
"
处理:
"
+
Convert.ToString(nProgress);
21
progressBarThread.Value
=
nProgress;
22
23
if
(nProgress
==
progressBarThread.Maximum)
24
{
25
MessageBox.Show(
"
Completed
"
);
26
this
.btnTread.Enabled
=
true
;
27
}
28
}
29
30
///
<summary>
31
///
Handles the Click event of the btnTread control.
32
///
</summary>
33
///
<param name="sender">
The source of the event.
</param>
34
///
<param name="e">
The
<see cref="System.EventArgs"/>
instance containing the event data.
</param>
35
private
void
btnTread_Click(
object
sender, EventArgs e)
36
{
37
TheDelegate
=
MessageHandler;
38
39
StartFrom
=
Convert.ToInt32(txtStart.Text);
40
EndTo
=
Convert.ToInt32(txtEnd.Text);
41
42
progressBarThread.Minimum
=
StartFrom;
43
progressBarThread.Maximum
=
EndTo;
44
45
btnTread.Enabled
=
false
;
46
47
IsThreadPaused
=
false
;
48
MyThread
=
new
Thread(ProcessRoutine);
49
MyThread.Start();
50
}
51
52
///
<summary>
53
///
Processes the routine.
54
///
</summary>
55
private
void
ProcessRoutine()
56
{
57
for
(
int
nValue
=
StartFrom; nValue
<=
EndTo; nValue
++
)
58
{
59
//
判断是否取消
60
if
(CancelEvent.WaitOne(
0
,
false
)
==
true
)
61
{
62
return
;
63
}
64
this
.BeginInvoke(
this
.TheDelegate, nValue);
65
Thread.Sleep(
200
);
66
}
67
}
68
69
///
<summary>
70
///
Handles the Click event of the btnCancelThread control.
71
///
</summary>
72
///
<param name="sender">
The source of the event.
</param>
73
///
<param name="e">
The
<see cref="System.EventArgs"/>
instance containing the event data.
</param>
74
private
void
btnCancelThread_Click(
object
sender, EventArgs e)
75
{
76
btnCancelThread.Enabled
=
false
;
77
btnPauseThread.Enabled
=
false
;
78
79
CancelEvent.Set();
80
MyThread.Join();
81
}
82
83
///
<summary>
84
///
Handles the Click event of the btnPauseThread control.
85
///
</summary>
86
///
<param name="sender">
The source of the event.
</param>
87
///
<param name="e">
The
<see cref="System.EventArgs"/>
instance containing the event data.
</param>
88
private
void
btnPauseThread_Click(
object
sender, EventArgs e)
89
{
90
//
Bad approach!
91
if
(
!
IsThreadPaused)
92
{
93
IsThreadPaused
=
true
;
94
MyThread.Suspend();
95
btnPauseThread.Text
=
"
Resume Thread
"
;
96
97
//
Disallow Cancel
98
btnCancelThread.Enabled
=
false
;
99
}
100
else
101
{
102
IsThreadPaused
=
false
;
103
MyThread.Resume();
104
btnPauseThread.Text
=
"
Pause Thread
"
;
105
btnCancelThread.Enabled
=
true
;
106
}
107
}
108
比较起来,两个是完全相同的,对于Thread来说,灵活性就比较好了,BackgroundWorker的使用就相对来说简单了。