【愚公系列】2023年11月 Winform控件专题 BackgroundWorker控件详解
🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏
🚀前言
Winform控件是Windows Forms中的用户界面元素,它们可以用于创建Windows应用程序的各种视觉和交互组件,例如按钮、标签、文本框、下拉列表框、复选框、单选框、进度条等。开发人员可以使用Winform控件来构建用户界面并响应用户的操作行为,从而创建功能强大的桌面应用程序。
🚀一、BackgroundWorker控件详解
BackgroundWorker控件是Windows Forms中提供的一个轻量级组件,用于在后台线程中执行耗时的操作,避免阻塞UI线程,提高应用程序的响应性能。BackgroundWorker控件通过在异步线程中执行操作,并在操作完成后在UI线程上引发事件来完成此目的。
BackgroundWorker控件提供了以下事件和方法,以方便在异步操作中实现进度报告、取消操作、完成操作等功能:
事件:
- DoWork:异步线程执行操作的事件。
- ProgressChanged:异步线程报告操作进度的事件。
- RunWorkerCompleted:异步操作完成时引发的事件。
方法:
- RunWorkerAsync:启动异步操作的方法。
- CancelAsync:请求取消异步操作的方法。
使用BackgroundWorker控件时,需要注意以下几点:
- 在DoWork事件中执行耗时的操作,不能调用UI线程上的控件,如需更新UI上的控件,需要在ProgressChanged事件中调用。
- 在RunWorkerCompleted事件中发生的任何异常都会被视为未处理异常,并导致应用程序崩溃。
- 如果需要在DoWork事件中定期检查是否已请求取消异步操作,可以使用CancellationPending属性,该属性为只读属性,如果已请求取消操作,则为true,否则为false。
🔎1.属性介绍
🦋1.1 WorkerReportsProgress
BackgroundWorker控件的WorkerReportsProgress属性用于指示是否支持异步报告进度。如果将其设置为true,则可以在异步操作中使用ReportProgress方法报告进度。如果设置为false,则不能使用ReportProgress方法,否则会引发InvalidOperationException异常。
WorkerReportsProgress属性的默认值为false。如果需要在异步操作中报告进度,则必须将其设置为true。
下面是一个示例,演示如何设置WorkerReportsProgress属性并在异步操作中报告进度:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// 设置WorkerReportsProgress属性为true
backgroundWorker1.WorkerReportsProgress = true;
// 执行耗时的操作
for (int i = 0; i <= 100; i++)
{
Thread.Sleep(50);
// 报告进度
backgroundWorker1.ReportProgress(i);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// 更新UI上的控件
progressBar1.Value = e.ProgressPercentage;
}
private void button1_Click(object sender, EventArgs e)
{
// 启动异步操作
backgroundWorker1.RunWorkerAsync();
}
在上述示例中,需要在DoWork事件中将WorkerReportsProgress属性设置为true,以启用ReportProgress方法,然后在循环中调用ReportProgress方法报告进度。在ProgressChanged事件中更新UI上的进度条控件。
🦋1.2 WorkerSupportsCancellation
BackgroundWorker控件是一个可用于执行后台操作的组件。它提供了一个异步操作模型,可以允许后台线程执行操作,并在操作完成后通知前台线程。
WorkerSupportsCancellation属性是BackgroundWorker控件的一个属性,用于指示后台操作是否支持取消。当WorkerSupportsCancellation属性设置为true时,可以通过调用BackgroundWorker控件的CancelAsync方法来请求取消后台操作。
下面是一个简单的示例,演示如何在Winform中使用BackgroundWorker控件和WorkerSupportsCancellation属性:
private BackgroundWorker backgroundWorker1;
private void buttonStart_Click(object sender, EventArgs e)
{
// 初始化BackgroundWorker控件
backgroundWorker1.WorkerSupportsCancellation = true;
// 启动异步操作
backgroundWorker1.RunWorkerAsync();
}
private void buttonCancel_Click(object sender, EventArgs e)
{
// 请求取消异步操作
backgroundWorker1.CancelAsync();
}
// 后台操作方法
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
backgroundWorker1.WorkerReportsProgress = true;
for (int i = 1; i <= 100; i++)
{
// 检查是否请求取消
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
break;
}
// 模拟长时间操作
Thread.Sleep(100);
// 更新进度条
backgroundWorker1.ReportProgress(i);
}
}
// 异步操作完成方法
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
MessageBox.Show("异步操作已取消!");
else if (e.Error != null)
MessageBox.Show("异步操作发生错误:" + e.Error.Message);
else
MessageBox.Show("异步操作已完成!");
}
在这个示例中,当点击“开始”按钮时,创建并启动BackgroundWorker控件,并在其中执行一个模拟的长时间操作。在操作执行过程中,每次更新进度条并检查是否请求取消。当点击“取消”按钮时,调用BackgroundWorker控件的CancelAsync方法来请求取消操作。当异步操作完成时,根据操作是否被取消或是否发生错误来显示相应的提示信息。
通过使用BackgroundWorker控件和WorkerSupportsCancellation属性,可以轻松实现异步操作的取消功能,提高应用程序的用户体验。
🔎2.常用场景
BackgroundWorker控件在Winform应用程序中的常用场景有:
-
长时间运行的任务:当需要执行耗时的操作时,比如读取大量数据、计算复杂算法、网络请求等,BackgroundWorker可以在后台执行,避免阻塞UI线程,提高用户体验。
-
操作进度条:在执行长时间运行的任务时,可以使用BackgroundWorker来更新进度条,让用户知道任务的进度和剩余时间。
-
异步处理问题:在Winform应用程序中,有时需要异步地执行某些操作,比如在窗口关闭时保存数据、进行数据同步等,BackgroundWorker可以帮助实现异步操作,避免阻塞UI线程。
-
实时更新UI:有些操作需要实时更新UI,比如显示传感器数据、播放音频等,BackgroundWorker可以在后台执行数据处理和更新UI,避免UI线程被阻塞。
🔎3.具体案例
以下是一个利用 BackgroundWorker 控件实现在后台线程中计算斐波那契数列,并将结果显示在 UI 上。
首先,在 UI 界面中添加一个 Label 控件用于显示结果,一个 Button 控件作为触发事件的按钮,以及一个 BackgroundWorker 控件。
在代码中,先引入 System.ComponentModel 命名空间,这个命名空间包含了 BackgroundWorker 类。
using System.ComponentModel;
在类中定义全局变量和 BackgroundWorker 对象:
public partial class Form1 : Form
{
private int n = 10; // 计算斐波那契数列的项数
private long[] fib; // 保存斐波那契数列的数组
private BackgroundWorker bgWorker; // BackgroundWorker 对象
public Form1()
{
InitializeComponent();
// 创建 BackgroundWorker 对象
bgWorker = new BackgroundWorker();
// 设置 WorkerReportsProgress 和 WorkerSupportsCancellation 属性
bgWorker.WorkerReportsProgress = true;
bgWorker.WorkerSupportsCancellation = true;
// 注册事件处理程序
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
}
// ...
}
接下来,定义 BackgroundWorker 的三个事件处理程序,分别是 DoWork、ProgressChanged 和 RunWorkerCompleted。这些事件将在后台线程中执行,并用于计算斐波那契数列、更新进度和显示结果。
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
// 计算斐波那契数列
fib = new long[n];
fib[0] = 0;
fib[1] = 1;
for (int i = 2; i < n; i++)
{
if (bgWorker.CancellationPending)
{
e.Cancel = true;
return;
}
fib[i] = fib[i - 2] + fib[i - 1];
int progress = (int)(((double)i / n) * 100);
bgWorker.ReportProgress(progress);
Thread.Sleep(100); // 模拟耗时操作
}
}
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// 显示进度条
progressBar1.Value = e.ProgressPercentage;
}
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// 显示结果
if (e.Cancelled)
{
label1.Text = "计算取消";
}
else if (e.Error != null)
{
label1.Text = "计算错误";
}
else
{
label1.Text = "结果:\n" + string.Join(", ", fib);
}
// 恢复按钮状态
button1.Enabled = true;
}
在按钮的 Click 事件处理程序中,开启 BackgroundWorker 的线程,并禁用按钮以防止用户重复点击。
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false; // 禁用按钮
// 开启线程
if (!bgWorker.IsBusy)
{
bgWorker.RunWorkerAsync();
}
}
最后,添加一个取消计算的按钮,并在其 Click 事件处理程序中调用 CancelAsync() 方法取消后台线程的计算。
private void button2_Click(object sender, EventArgs e)
{
if (bgWorker.IsBusy)
{
bgWorker.CancelAsync();
}
}
完整代码:
using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;
namespace BackgroundWorkerExample
{
public partial class Form1 : Form
{
private int n = 10; // 计算斐波那契数列的项数
private long[] fib; // 保存斐波那契数列的数组
private BackgroundWorker bgWorker; // BackgroundWorker 对象
public Form1()
{
InitializeComponent();
// 创建 BackgroundWorker 对象
bgWorker = new BackgroundWorker();
// 设置 WorkerReportsProgress 和 WorkerSupportsCancellation 属性
bgWorker.WorkerReportsProgress = true;
bgWorker.WorkerSupportsCancellation = true;
// 注册事件处理程序
bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
}
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false; // 禁用按钮
// 开启线程
if (!bgWorker.IsBusy)
{
bgWorker.RunWorkerAsync();
}
}
private void button2_Click(object sender, EventArgs e)
{
if (bgWorker.IsBusy)
{
bgWorker.CancelAsync();
}
}
private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
// 计算斐波那契数列
fib = new long[n];
fib[0] = 0;
fib[1] = 1;
for (int i = 2; i < n; i++)
{
if (bgWorker.CancellationPending)
{
e.Cancel = true;
return;
}
fib[i] = fib[i - 2] + fib[i - 1];
int progress = (int)(((double)i / n) * 100);
bgWorker.ReportProgress(progress);
Thread.Sleep(100); // 模拟耗时操作
}
}
private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// 显示进度条
progressBar1.Value = e.ProgressPercentage;
}
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// 显示结果
if (e.Cancelled)
{
label1.Text = "计算取消";
}
else if (e.Error != null)
{
label1.Text = "计算错误";
}
else
{
label1.Text = "结果:\n" + string.Join(", ", fib);
}
// 恢复按钮状态
button1.Enabled = true;
}
}
}
🚀感谢:给读者的一封信
亲爱的读者,
我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。
如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。
我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。
如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。
![在这里插入图片描述](https://img-blog.csdnimg.cn/e06a317e89694a23ad89d2c59538c3a1.jpeg#pic_center =450x300)
再次感谢您的阅读和支持!
最诚挚的问候, “愚公搬代码”
- 点赞
- 收藏
- 关注作者
评论(0)