WPF之BackgroundWorker
BackgroundWorker类允许您在单独的线程上执行某个可能导致用户界面(UI)停止响应的耗时操作,下面来介绍一下这个线程类BackgroundWorker,大家可以结合这位大佬的这篇文章,说的比较仔细
https://www.cnblogs.com/zhaoshujie/p/9634136.html
1.属性
//bool类型,指示应用程序是否已请求取消后台操作。此属性通常放在用户执行的异步操作内部,用来判断用户是否取消执行异步操作。当执行BackgroundWorker.CancelAsync()方法时,该属性值将变为True。
public bool CancellationPending { get; }
//bool类型,指示BackgroundWorker是否正在执行一个异步操作。此属性通常放在BackgroundWorker.RunWorkerAsync()方法之前,避免多次调用RunWorkerAsync()方法引发异常。当执行BackgroundWorker.RunWorkerAsync()方法是,该属性值将变为True。public bool IsBusy { get; }
//bool类型,指示BackgroundWorker是否可以报告进度更新。当该属性值为True是,将可以成功调用ReportProgress方法,默认为false
public bool WorkerReportsProgress { get; set; }
//bool类型,指示BackgroundWorker是否支持异步取消操作。当该属性值为True是,将可以成功调用CancelAsync方法取消工作线程。
public bool WorkerSupportsCancellation { get; set; }
2.方法
//取消线程操作,属性CancellationPending
将变为True
public void CancelAsync ();
//执行该方法,将触发ProgressChanged事件
public void ReportProgress (int percentProgress);
//开始执行线程操作,触发DoWork事件,执行事件中的代码
public void RunWorkerAsync ();
3.事件
//当执行RunWorkerAsync方法的时候触发该事件
public event System.ComponentModel.DoWorkEventHandler DoWork;
//当执行ReportProgress方法的时候触发该事件
public event System.ComponentModel.ProgressChangedEventHandler ProgressChanged;
//当线程操作完成、或者被取消、或者抛出异常的时候触发该事件
public event System.ComponentModel.RunWorkerCompletedEventHandler RunWorkerCompleted;
4.接下来通过一个开始/结束/暂停/继续执行线程的例子来说明
namespace LoginUI { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class LoadingWindow : Window {private BackgroundWorker _backgroundWorker;
//初始化为终止状态(true),那么该方法将一直工作 private ManualResetEvent manualReset = new ManualResetEvent(true);public LoadingWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { #region InitializeBackgroundWorker(); btnSatrt.Content = "开始"; btnStop.Content = "暂停"; btnEnd.Content = "结束"; #endregion } //执行后台线程 private void btnSatrt_Click(object sender, RoutedEventArgs e) { //开始执行后台操作 _backgroundWorker.RunWorkerAsync(); btnSatrt.IsEnabled = false; btnEnd.IsEnabled = true; } //暂停/继续后台线程 private void btnStop_Click(object sender, RoutedEventArgs e) { if (btnStop.Content.ToString() == "暂停") { manualReset.Reset();//暂停当前线程的工作,发信号给waitOne方法,阻塞 btnStop.Content = "继续"; } else { manualReset.Set();//继续当前线程的工作,发信号给waitOne方法,继续运行Waitone后面的代码 btnStop.Content = "暂停"; } } //结束后台线程 private void btnEnd_Click(object sender, RoutedEventArgs e) { _backgroundWorker.CancelAsync(); btnSatrt.IsEnabled = true; btnEnd.IsEnabled = false; } private void InitializeBackgroundWorker() { #region if (_backgroundWorker == null) _backgroundWorker = new BackgroundWorker(); //bool类型,指示BackgroundWorker是否可以报告进度更新。当该属性值为True时,将可以成功调用ReportProgress方法 _backgroundWorker.WorkerReportsProgress = true; //bool类型,指示BackgroundWorker是否支持异步取消操作。当该属性值为True是,将可以成功调用CancelAsync方法 _backgroundWorker.WorkerSupportsCancellation = true; //执行RunWorkerAsync方法后触发DoWork,将异步执行backgroundWorker_DoWork方法中的代码 _backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork); //执行ReportProgress方法后触发ProgressChanged,将执行ProgressChanged方法中的代码 _backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(_backgroundWorker_ProgressChanged); //异步操作完成或取消时执行的操作,当调用DoWork事件执行完成时触发。 _backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted); #endregion } //backgroundWorker_DoWork完成后执行 private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if((bool)e.Result==true) { progressBar.Value = 100; lstbLog.Items.Add("操作已完成"); MessageBox.Show("操作已完成"); } } private void _backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) {
//ProgressPercentage是ReportProgress方法中第一个参数传递过来的 progressBar.Value = e.ProgressPercentage;
//lstbLog是一个listView控件,UserState是ReportProgress方法中第二个参数传递过来的 lstbLog.Items.Add(e.UserState.ToString()); } //backgroundWorker_DoWork是运行在非UI线程上的,因此该内部代码应该避免与UI界面交互,交互的逻辑应该放到 //ProgressChanged和RunWorkerCompleted事件中 private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { for (int i=0;i<=100;i++) { ////如果ManualResetEvent的初始化为终止状态(true),那么该方法将一直工作, //直到收到Reset信号,将阻塞。然后,直到收到Set信号,就继续工作。 manualReset.WaitOne(); //可以通过调用CancelAsync方法设置CancellationPending的值为false if (_backgroundWorker.CancellationPending) { _backgroundWorker.ReportProgress(i, String.Format("{0}%,操作被用户申请结束", i)); _backgroundWorker.ReportProgress(0, String.Format("已完成{0}%",0 )); e.Result = false; break; } //调用 ReportProgress 方法,会触发ProgressChanged事件 _backgroundWorker.ReportProgress(i, String.Format("已完成{0}%", i)); System.Threading.Thread.Sleep(50); if (i == 100) { //执行DoWork方法完成,设置为True e.Result = true; } } }
点击开始按钮,开始执行

点击结束,将会结束上述任务
点击暂停/继续按钮可以暂停/继续当前任务
上述每个按钮的功能逻辑还没有完善,但是基本的功能都实现了。本人也是个新手,如有什么问题麻烦指出,谢谢各位大佬!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端