如果某项操作需要很长时间才能完成,而你不希望造成用户界面的延迟,则可以使用?BackgroundWorker?类在另一个线程上运行此操作。
当窗体在 Visual Studio 中的 Windows 窗体设计器中处于活动状态时,将两个?Button?控件从“工具箱”拖动到窗体中,然后根据下表设置按钮的?Name
?和?Text?属性。
展开表
Button | 名称 | 文本 |
---|---|---|
button1 | startBtn | 开始 |
button2 | cancelBtn | Cancel |
打开“工具箱”,单击“组件”选项卡,然后将?BackgroundWorker?组件拖动到窗体上。
backgroundWorker1
?组件显示在“组件栏”中。
在“属性”?窗口中,将?WorkerSupportsCancellation?属性设置为?true
。
在“属性”窗口中,单击“事件”按钮,然后双击?DoWork?和?RunWorkerCompleted?事件以创建事件处理程序。
将耗时的代码插入?DoWork?事件处理程序。
从参数?DoWorkEventArgs?的?Argument?属性中提取操作所需的任何参数。
将计算结果分配给?DoWorkEventArgs?的?Result?属性。
此结果将可供?RunWorkerCompleted?事件处理程序使用。
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// Do not access the form's BackgroundWorker reference directly.
// Instead, use the reference provided by the sender parameter.
BackgroundWorker bw = sender as BackgroundWorker;
// Extract the argument.
int arg = (int)e.Argument;
// Start the time-consuming operation.
e.Result = TimeConsumingOperation(bw, arg);
// If the operation was canceled by the user,
// set the DoWorkEventArgs.Cancel property to true.
if (bw.CancellationPending)
{
e.Cancel = true;
}
}
在?RunWorkerCompleted?事件处理程序中插入用于检索操作结果的代码。
// This event handler demonstrates how to interpret
// the outcome of the asynchronous operation implemented
// in the DoWork event handler.
private void backgroundWorker1_RunWorkerCompleted(
object sender,
RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
// The user canceled the operation.
MessageBox.Show("Operation was canceled");
}
else if (e.Error != null)
{
// There was an error during the operation.
string msg = String.Format("An error occurred: {0}", e.Error.Message);
MessageBox.Show(msg);
}
else
{
// The operation completed normally.
string msg = String.Format("Result = {0}", e.Result);
MessageBox.Show(msg);
}
}
实现?TimeConsumingOperation
?方法。
// This method models an operation that may take a long time
// to run. It can be cancelled, it can raise an exception,
// or it can exit normally and return a result. These outcomes
// are chosen randomly.
private int TimeConsumingOperation(
BackgroundWorker bw,
int sleepPeriod )
{
int result = 0;
Random rand = new Random();
while (!bw.CancellationPending)
{
bool exit = false;
switch (rand.Next(3))
{
// Raise an exception.
case 0:
{
throw new Exception("An error condition occurred.");
break;
}
// Sleep for the number of milliseconds
// specified by the sleepPeriod parameter.
case 1:
{
Thread.Sleep(sleepPeriod);
break;
}
// Exit and return normally.
case 2:
{
result = 23;
exit = true;
break;
}
default:
{
break;
}
}
if( exit )
{
break;
}
}
return result;
}
在 Windows 窗体设计器中,双击?startButton
?以创建?Click?事件处理程序。
调用?startButton
?的?Click?事件处理程序中的?RunWorkerAsync?方法。
private void startBtn_Click(object sender, EventArgs e)
{
this.backgroundWorker1.RunWorkerAsync(2000);
}
在 Windows 窗体设计器中,双击?cancelButton
?以创建?Click?事件处理程序。
调用?cancelButton
?的?Click?事件处理程序中的?CancelAsync?方法。
private void cancelBtn_Click(object sender, EventArgs e)
{
this.backgroundWorker1.CancelAsync();
}
在文件的顶部,导入 System.ComponentModel 和 System.Threading 命名空间。
using System;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
按 F6 生成解决方案,然后按 Ctrl+F5 在调试程序外部运行应用程序。
?备注
如果按 F5 在调试程序下运行应用程序,则调试程序将捕获并显示?TimeConsumingOperation
?方法中引发的异常。 在调试程序外部运行应用程序时,BackgroundWorker?将处理异常并将其缓存到?RunWorkerCompletedEventArgs?的?Error?属性中。
单击“启动”按钮以运行异步操作,然后单击“取消”按钮以停止正在运行的异步操作。
每个操作的结果显示在?MessageBox?中。