使用winform BackgroundWorker组件执行多线程任务

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
bgWorker.WorkerReportsProgress = true;//报告完成进度
bgWorker.WorkerSupportsCancellation = true;//允许用户终止后台线程
bgWorker.DoWork += BgWorker_DoWork;
bgWorker.RunWorkerCompleted += BgWorker_RunWorkerCompleted;
bgWorker.ProgressChanged += BgWorker_ProgressChanged;
}

 private void btnStart_Click(object sender, EventArgs e)
 {
     //判断backgroundWorker1是否正在运行异步操作
     if (!bgWorker.IsBusy)
     {
         //开始执行后台异步操作,调用DoWork事件
         bgWorker.RunWorkerAsync(100);
     }
     //等待后台运行完毕
     while (bgWorker.IsBusy)
     {
         Application.DoEvents();
     }
     MessageBox.Show("操作完成");
 }

 private void btnStop_Click(object sender, EventArgs e)
 {
     if (bgWorker.WorkerSupportsCancellation)
     { 
         bgWorker.CancelAsync();//取消后台操作
         bgWorker.Dispose();//释放资源
     }
 }

 //DoWork事件声明要执行的耗时操作
 private void BgWorker_DoWork(object sender, DoWorkEventArgs e)
 {
     BackgroundWorker backgroundWorker = sender as BackgroundWorker;
     e.Result = ListNumber(backgroundWorker, e);//运算结果保存在e.Result中(在RunWorkerCompleted事件可能会使用到)
 }

 bool ListNumber(object sender, DoWorkEventArgs e)
 {
     int num = (int)e.Argument;//接收传入的参数,即RunWorkerAsync(object argument)传入的值
     for (int i = 1; i <= num; i++)
     {
         if (bgWorker.CancellationPending)//判断是否请求了取消后台操作,如果为false则退出
         {
             e.Cancel = true;//e.Cancel 是否应该取消事件
             return false;
         }
         Thread.Sleep(10);//执行一个耗时操作
         bgWorker.ReportProgress(i * 100 / num, i);//报告完成进度,该方法会触发ProgressChanged事件

     }
     return true;
 }

 //ReportProgress该方法触发ProgressChanged事件,在ProgressChanged事件中接收报告完成进度参数
 private void BgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
 {
     progressBar1.Value = e.ProgressPercentage;//将完成进度数据传给进度条
     //label1.Text = e.ProgressPercentage + "%";
     ////另开一个线程上设置Label的属性
     Thread thread = new Thread(delegate(object parameter)
     {
         SetLabel(parameter);
     });
     thread.Start(e.ProgressPercentage);
     //将中间计算结果在ListBox控件中显示出来
     listBox1.Items.Add(e.UserState);//接收ReportProgress方法传递过来的userState
 }

 private void BgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
 {
     if (e.Cancelled == true) //e.Cancelled指示异步操作是否已被取消
     {
         MessageBox.Show("Canceled!");
     }
     else if (e.Error != null) //e.Error 指示异步操作期间发生的错误
     {
         MessageBox.Show("Error: " + e.Error.Message);
     }
     else
     {
         MessageBox.Show(e.Result.ToString());  //e.Result 获取异步操作结果的值,即DoWork事件中,Result设置的值。
     }

 }
  
 delegate void Action(int args);//Net3.5自带的Action无参数无返回值
 private void SetLabel(object ProgressPercentage)
 {
     int progressPercentage = 0;
     int.TryParse($"{ProgressPercentage}", out progressPercentage);
     Action action = delegate (int args)
     {
         this.label1.Text = args + "%";
     };
     if (this.InvokeRequired)//判断当前代码是运行于创建该控件的线程之上,还是运行于另一个线程之上。
         this.Invoke(action, progressPercentage);//注意控件的Inovoke和BeginInvoke委托的方法都执行在UI线程上。对Control的Invoke方法可以使用一个简单的系统委托MethodInvoker无参数返回Void调用。
     else
         action(progressPercentage);
 }

}

posted @   .Net菜鸟站  阅读(65)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示