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窗体上,界面如图:
后台代码:
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();
}
}
}
运行界面:
操作完成界面:
接收返回值:
取消后台操作:
来源:https://www.cnblogs.com/dotnet261010/p/5942034.html


猜你喜欢
- 前言平时的工作中经常碰到很多疑难问题的处理,在解决问题的同时,有一些工具起到了相当大的作用,在此书写下来,一是作为笔记,可以让自己后续忘记了
- 一、项目简述功能javaweb 网上商城系统,前台+后台管理,用户注册,登录,上哦展示,分组展示,搜索,收货地址管理,购物车管理,添加,购买
- 我们在平常项目开发中,经常会用到周期性定时任务,这个时候使用定时任务就能很方便的实现。在SpringBoot中用得最多的就是Schedule
- 本文实例为大家分享了Java实现多人聊天室的具体代码,供大家参考,具体内容如下先说,记录本人的学习过程,当笔记了多人聊天室分为1.服务器①.
- 题目描述:在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数
- clone()和Cloneable接口clone顾名思义就是克隆,即,复制一个相等的对象,但是不同的引用地址。我们知道拿到一个对象的地址,只
- 本文实例讲述了Android编程中沉浸式状态栏的三种实现方式。分享给大家供大家参考,具体如下:沉浸式状态栏Google从android ki
- 问题用过storm或者jstorm的都知道,如果在bolt代码中发生了没被catch住的异常,所在worker进程会退出。本文就从源码角度分
- 一、新建一个as项目,再新建一个model模块然后再app中的build.gradle中添加model的依赖。然后编译项目。二、编译完成后,
- 实例描述现有某班学生的两份成绩,两份成绩中存在一些不一致的记录。需借助于编程方法找出这些不一致的记录。实例代码using System;us
- 为了方便客户抓取Log,现通过TCP协议连接指定服务器,传输指定内容,定义指定目录,IP,PORT字段接收参数。直接上代码 public s
- 代码public class LamdaDemo{ public static void main( String[] args
- 前几天在琢磨mybatis xml热加载的问题,原理还是通过定时扫描xml文件去跟新,但放到项目上就各种问题,由于用了mybatisplus
- 现象说明maven的java项目,测试用例和main所在的源码文件均符合缺省写法和格式,但是在使用mvn clean sonar:sonar
- RecyclerView目前来说对大家可能不陌生了。由于在公司的项目中,我们一直用的listview和gridview。某天产品设计仿照美团
- 本文实例讲述了Android编程实现拍照功能的2种方法。分享给大家供大家参考,具体如下:Android系统的照相功能,已实现2种方法,可供大
- 本文同时讨论了IComparable和IComparer接口,原因有两点。这两个接口经常一起使用。虽然接口类似且名称相似,但它们却有不同的用
- 本文实例为大家分享了C语言实现五子棋游戏的具体代码,供大家参考,具体内容如下一、实现的目的和意义1、巩固和加深对c语言知识的理解2、学会使用
- 引例问题:现在有一只羊(包含属性:名字Dolly、年龄2),需要克隆10只属性完全相同的羊。一般解法:定义Sheep类表示羊,包括构造器、g
- 前言 这其实是一道面试题,是我在面试百度的时候被问到的,当时没有答出来(因为自己真的很菜),后来在网上寻找答案,看到也是一头雾水,