WinForm多线程组件BackgroundWorker是一种方便且易于使用的组件,可以使多线程编程变得更加容易。以下是使用BackgroundWorker时需要注意的事项:
什么是BackgroundWorker
BackgroundWorker是一个WinForm多线程组件,可以在后台执行操作,通常可以将花费时间很长的任务放在后台线程中执行,而不会阻塞UI线程。 BackgroundWorker组件提供了三个事件:DoWork、ProgressChanged和RunWorkerCompleted。当你在后台执行操作时,可以将进度信息报告给UI线程,并在运行结束时调用RunWorkerCompleted事件。
创建BackgroundWorker
在设计模式下,你可以从工具菜单中选择BackgroundWorker组件并将其拖拽到WinForm窗体中。然后,通过检查属性窗口上的worker属性来设置背景工作器的属性,例如:WorkerReportsProgress属性(指示是否应在进度更改时通知UI线程)和WorkerSupportsCancellation属性(指示背景工作器是否支持取消操作)。或者,你可以在代码中直接创建BackgroundWorker实例,例如:
private BackgroundWorker _worker = new BackgroundWorker();
启动BackgroundWorker
要启动BackgroundWorker,你可以通过调用RunWorkerAsync方法,例如:
_worker.RunWorkerAsync();
你可以选择将StartNewWorker方法绑定到按钮的Click事件上,例如:
private void btnStartWorker_Click(object sender, EventArgs e)
{
_worker.RunWorkerAsync();
}
实现DoWork事件
DoWork事件是BackgroundWorker中最重要的事件,必须在该事件中编写实际要执行的代码。该事件会在后台线程上执行,因此不能直接从DoWork事件访问UI元素。如果需要更新进度,可以调用ReportProgress方法,向UI线程报告进度,例如:
private void _worker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(100);
_worker.ReportProgress(i);
}
}
更新UI元素
如果需要在DoWork事件中更新UI元素,可以将ReportProgress方法的UserState属性设置为要发送给UI线程的对象。通过ReportProgress方法发送对象到UI线程,可以在ProgressChanged事件中读取该对象并更新UI元素,例如:
private void _worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
lblPercentComplete.Text = e.ProgressPercentage.ToString() + "%";
progressBar.Value = e.ProgressPercentage;
if (e.UserState != null)
{
string message = (string)e.UserState;
MessageBox.Show(message);
}
}
实现RunWorkerCompleted事件
在DoWork事件完成后,RunWorkerCompleted事件将被引发。在该事件中,您可以执行任何喜欢的操作,并在需要时检查错误并从异常中提取错误消息。例如:
private void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
MessageBox.Show("任务已取消。");
}
else if (e.Error != null)
{
MessageBox.Show("错误:" + e.Error.Message);
}
else
{
MessageBox.Show("任务已完成。");
}
}
示例1:简单的后台操作
在此示例中,我们将会显示一个包含一个按钮和一个进度条的窗体。单击按钮将在后台线程上执行任务,并在进度条上报告进度。当任务完成时,我们将在UI线程上显示消息。
private void btnStartWorker_Click(object sender, EventArgs e)
{
_worker.WorkerReportsProgress = true;
_worker.WorkerSupportsCancellation = true;
_worker.DoWork += new DoWorkEventHandler(_worker_DoWork);
_worker.ProgressChanged += new ProgressChangedEventHandler(_worker_ProgressChanged);
_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_worker_RunWorkerCompleted);
_worker.RunWorkerAsync();
}
private void _worker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(100);
_worker.ReportProgress(i);
}
e.Result = "任务已完成";
}
private void _worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
lblPercentComplete.Text = e.ProgressPercentage.ToString() + "%";
}
private void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
MessageBox.Show("任务已取消");
}
else if (e.Error != null)
{
MessageBox.Show("错误:" + e.Error.Message);
}
else
{
string result = (string)e.Result;
MessageBox.Show(result);
}
}
示例2:取消后台操作
此示例演示了如何取消后台操作。当用户单击“取消”按钮时,将取消后台任务。当任务被取消时,我们将在UI线程上显示消息。
private void btnStartWorker_Click(object sender, EventArgs e)
{
_worker.WorkerReportsProgress = true;
_worker.WorkerSupportsCancellation = true;
_worker.DoWork += new DoWorkEventHandler(_worker_DoWork);
_worker.ProgressChanged += new ProgressChangedEventHandler(_worker_ProgressChanged);
_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_worker_RunWorkerCompleted);
_worker.RunWorkerAsync();
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (_worker.IsBusy)
{
_worker.CancelAsync();
}
}
private void _worker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 1; i <= 100; i++)
{
if (_worker.CancellationPending)
{
e.Cancel = true;
return;
}
Thread.Sleep(100);
_worker.ReportProgress(i);
}
e.Result = "任务已完成";
}
private void _worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
lblPercentComplete.Text = e.ProgressPercentage.ToString() + "%";
}
private void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
MessageBox.Show("任务已取消");
}
else if (e.Error != null)
{
MessageBox.Show("错误:" + e.Error.Message);
}
else
{
string result = (string)e.Result;
MessageBox.Show(result);
}
}
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:winform多线程组件BackgroundWorker使用 - Python技术站