C#使用BackgroundWorker控件

作者:.NET开发菜鸟 时间:2022-10-25 05:06:35 

在我们的程序中,经常会有一些耗时较长的运算,为了保证用户体验,不引起界面不响应,我们一般会采用多线程操作,让耗时操作在后台完成,完成后再进行处理或给出提示,在运行中,也会时时去刷新界面上的进度条等显示,必要时还要控制后台线程中断当前操作。

在.net中,提供了一个组件BackgroundWorker就是专门解决这个问题的。BackgroundWorker类允许在单独的专用线程上运行操作。 耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面(UI)似乎处于停止响应状态。如果需要能进行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用BackgroundWorker类方便地解决问题。

程序执行步骤:

  • 1、调用BackgroundWorker的RunWorkerAsync()方法,如果后台操作需要参数,在调用RunWorkerAsync()方法时给出参数,在DoWork事件处理程序内部,可以从DoWorkEventArgs.Argument属性中提取该参数。

  • 2、执行DoWork事件,后台需要执行的代码放到DoWork事件里面执行。当调用RunWorkerAsync()方法时,BackgroundWorker通过触发DoWork事件,开始执行后台操作

显示后台操作进度:

为了显示后台操作的执行进度,首先要使WorkerReportsProgress等于true,然后调用BackgroundWorker的ReportProgress()方法,通过它传递操作完成的进度值,此外,该方法触发ProgressChanged事件,在此事件中,通过ProgressChangedEventArgs的实例,接收到主线程传递过来的参数。

取消后台操作:

为了使 BackgroundWorker 可以取消后台正在执行的操作,首先要把属性WorkerSupportsCancellation 的值设置为 true。接着调用CancelAsync()方法,该方法使得属性CancellationPending 为true,利用CancellationPending 属性,可以判断是否取消后台异步操作。

后台操作完成后,反馈给用户:

当后台操作完成以后,无论是completed 还是cancelled,RunWorkerCompleted()事件都会被触发,通过此方法可以将后台操作的完成结果反馈给用户。RunWorkerCompleted 事件处理函数会在DoWork 事件处理函数返回后被调用。通过它我们可以进行一些运算结束后的操作,比如禁用取消按钮,异常处理,结果显示等。注意,如果想要拿到e.Result,您需要在BGWorker_DoWork方法中设置 e.Result属性另外,通过RunWorkerCompletedEventArgs实例的Cancelled 属性,以判断是否是Cancel操作使得后台操作终止;

从后台操作返回值

在执行DoWork事件时DoWorkEventArgs实例的Result属性,返回值到用户;在RunWorkerCompleted事件里,RunWorkerCompletedEventArgs 实例的Result属性接收值;

创建BackgroundWorkerDemo例子:

  • 1.新建一个windows窗体应用程序,如:BackgroundWorkerDemo

  • 2.拖一个ProgressBar(进度条)和一个BackgroundWorker控件到Form窗体上,界面如图:

C#使用BackgroundWorker控件

后台代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace BackgroundWorkerDemo
{
   public partial class FrmDemo : Form
   {
       //设置生成临时文件的路径
       static string strSaveDir = @"F:\培训";
       public FrmDemo()
       {
           InitializeComponent();

//显示后台操作的执行进度
           this.bgWork.WorkerReportsProgress = true;
           //可以取消后台正在执行的操作
           this.bgWork.WorkerSupportsCancellation = true;
       }

/// <summary>
       /// 开始
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void btn_Start_Click(object sender, EventArgs e)
       {
           if (Directory.Exists(strSaveDir) == false)
           {
               return;
           }
           btn_Start.Enabled = false;
           int count = Convert.ToInt32(this.txt_File.Text.ToString().Trim());
           //设置进度条
           this.proBar.Minimum = 0;
           this.proBar.Maximum = count;
           this.proBar.Value = this.proBar.Minimum;
           //开始执行异步线程,进行后台操作,给后台传递参数
           this.bgWork.RunWorkerAsync(count);
       }

/// <summary>
       /// 后台操作要处理的任务代码
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void bgWork_DoWork(object sender, DoWorkEventArgs e)
       {
           //获取从RunWorkerAsync()方法里面传递的参数的值
           int fileCount= Convert.ToInt32(e.Argument);
           Random rand = new Random();
           byte[] buffer = new byte[2048];
           for (int i = 0; i < fileCount; i++)
           {
               try
               {
                   string strFileName = Path.Combine(strSaveDir, i.ToString() + ".tmp");
                   using (var stream = File.Create(strFileName))
                   {
                       int n = 0;
                       int maxByte = 8 * 1024 * 1024;
                       while (n < maxByte)
                       {
                           rand.NextBytes(buffer);
                           stream.Write(buffer, 0, buffer.Length);
                           n += buffer.Length;
                       }
                   }
               }
               catch (Exception ex)
               {
                   continue;
               }
               finally
               {
                   //报告进度
                   this.bgWork.ReportProgress(i + 1);
                   Thread.Sleep(100);
               }

//判断是否取消了后台操作
               if (bgWork.CancellationPending)
               {
                   e.Cancel = true;
                   return;
               }

//设置返回值
               e.Result = 234;
           }
       }

/// <summary>
       /// 更新前台界面进度条
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void bgWork_ProgressChanged(object sender, ProgressChangedEventArgs e)
       {
           //获取异步任务的进度百分百
           int val = e.ProgressPercentage;
           this.label2.Text = string.Format("已经生成{0}个文件", val);
           //进度条显示当前进度
           this.proBar.Value = val;
       }

/// <summary>
       /// 后台操作完成,向前台反馈信息
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void bgWork_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
       {
           btn_Start.Enabled = true;
           //用户取消操作(e.Cancelled==true,表示异步操作已被取消)
           if (e.Cancelled)
           {
               MessageBox.Show("用户取消后台操作", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
           }
           else
           {
               MessageBox.Show("操作完成", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);

//接收返回值
               int result = (int)e.Result;

MessageBox.Show("返回值:" + result);
           }
       }

/// <summary>
       /// 取消
       /// </summary>
       /// <param name="sender"></param>
       /// <param name="e"></param>
       private void btn_Cancle_Click(object sender, EventArgs e)
       {
           //调用CancelAsync(),取消挂起的后台操作
           this.bgWork.CancelAsync();
       }
   }
}

运行界面:

C#使用BackgroundWorker控件

操作完成界面:

C#使用BackgroundWorker控件

接收返回值:

C#使用BackgroundWorker控件

取消后台操作:

C#使用BackgroundWorker控件

来源:https://www.cnblogs.com/dotnet261010/p/5942034.html

标签:C#,BackgroundWorker,控件
0
投稿

猜你喜欢

  • Java+TestNG接口自动化入门详解

    2023-11-05 04:37:58
  • VS2022+unity3D开发环境搭建的实现步骤

    2023-02-10 10:13:47
  • Java Volatile 变量详解及使用方法

    2023-03-13 13:27:10
  • Spring 自动装配的二义性实例解析

    2021-12-16 00:37:55
  • hibernate 命名查询如何实现

    2023-11-04 02:35:41
  • Java线程的基本概念

    2022-05-20 16:30:22
  • asp.net实现遍历Request的信息操作示例

    2022-11-15 23:15:18
  • java 中的instanceof用法详解及instanceof是什么意思(推荐)

    2023-06-07 13:52:27
  • java并发编程专题(五)----详解(JUC)ReentrantLock

    2023-12-01 04:04:09
  • SpringCloud Feign远程调用实现详解

    2021-09-28 11:35:15
  • 在C#中 webbrowser的使用心得

    2023-12-10 12:57:00
  • Andriod使用多线程实现轮播图片

    2023-07-27 15:47:31
  • Java定时任务的三种实现方法

    2022-01-13 06:59:01
  • Spring Boot右键maven build成功但是直接运行main方法出错的解决方案

    2021-08-22 00:21:26
  • Mybatis接口式编程的原理

    2023-11-27 22:16:05
  • Java线程优先级和守护线程原理解析

    2023-03-27 16:45:30
  • java 中锁的性能提高办法

    2021-07-28 10:50:28
  • Android如何利用RecyclerView实现列表倒计时效果实例代码

    2023-01-24 08:08:53
  • Andoroid实现底部图片选择Dialog效果

    2022-11-11 22:41:03
  • Java实现文件和base64流的相互转换功能示例

    2023-11-18 07:45:01
  • asp之家 软件编程 m.aspxhome.com