C# backgroundworker类(后台线程)

概念

在C#程序中,经常会有一些耗时较长的CPU密集型运算,如果直接在 UI 线程执行这样的运算就会出现UI不响应的问题。解决这类问题的主要途径是使用多线程,启动一个后台线程,把运算操作放在这个后台线程中完成。但是原生接口的线程操作有一些难度,如果要更进一步的去完成线程间的通信就会难上加难。

C#的BackgroundWorker类是一个用于简化在桌面应用程序(如Windows Forms或WPF)中执行后台任务的工具。它的主要目的是在不阻塞用户界面(UI)的情况下运行耗时操作,同时支持进度报告和任务取消。

主要作用

后台执行耗时任务
在单独的线程中运行长时间操作(如文件下载、数据处理),防止UI线程被阻塞,保持界面响应。

进度更新
允许在后台任务中报告进度(如更新进度条),并自动将更新操作同步到UI线程。

取消支持
提供机制让用户请求取消正在执行的后台任务。

完成通知
在任务完成(成功、取消或出错)后,触发事件以更新UI或处理结果。


关键成员

成员类型说明
DoWork事件后台任务逻辑:在此事件处理程序中编写耗时操作代码。此代码在后台线程执行。
ProgressChanged事件进度更新:通过ReportProgress()方法触发,用于在UI上更新进度(如进度条)。
RunWorkerCompleted事件任务完成通知:在任务结束时触发,处理结果或错误。
RunWorkerAsync()方法启动后台任务
CancelAsync()方法请求取消任务(需设置WorkerSupportsCancellation = true)。
WorkerReportsProgress属性设置为true以启用进度报告功能。
WorkerSupportsCancellation属性设置为true以允许任务取消。


典型使用场景

// 创建BackgroundWorker实例
var worker = new BackgroundWorker 
{ 
    WorkerReportsProgress = true,
    WorkerSupportsCancellation = true 
};

// 订阅事件
worker.DoWork += (sender, e) => 
{
    for (int i = 0; i <= 100; i++) 
    {
        if (worker.CancellationPending) 
        {
            e.Cancel = true;
            return;
        }
        // 模拟耗时操作并报告进度
        worker.ReportProgress(i);
        Thread.Sleep(50);
    }
};

worker.ProgressChanged += (sender, e) => 
{
    // 更新UI进度条(自动在UI线程执行)
    progressBar.Value = e.ProgressPercentage;
};

worker.RunWorkerCompleted += (sender, e) => 
{
    if (e.Cancelled) MessageBox.Show("任务已取消!");
    else if (e.Error != null) MessageBox.Show($"错误:{e.Error.Message}");
    else MessageBox.Show("任务完成!");
};

// 启动任务
worker.RunWorkerAsync();


 

注意事项

  1. 跨线程访问UI

    • DoWork事件在后台线程运行,禁止直接操作UI控件

    • ProgressChangedRunWorkerCompleted事件会自动在UI线程触发,可直接更新UI。

  2. 替代方案
    现代C#更推荐使用async/await配合Task.Run处理异步操作,代码更简洁。但BackgroundWorker仍适用于旧项目或需要深度集成进度/取消逻辑的场景。


与async/await对比

特性BackgroundWorkerasync/await + Task.Run
复杂度基于事件,代码分散线性结构,代码更清晰
取消支持内置CancellationPending机制通过CancellationToken实现
进度报告内置ReportProgress需自定义(如IProgress<T>接口)
适用场景简单后台任务复杂异步操作,需更高灵活性

总结:BackgroundWorker是简化桌面应用后台任务处理的经典工具,适合需要快速实现进度更新和取消功能的场景。但在新项目中,可优先考虑async/await以获得更现代的编程体验。


实例(源码)

public partial class Form2 : Form
{
    public  BackgroundWorker worker = new BackgroundWorker();

    public Form2()
    {
        InitializeComponent();
    }

    private void Form2_Load(object sender, EventArgs e)
    {
        // Worker 工人
        // Reports 报告
        // Progress 进度
        // WorkeyRepoetsProgress 是否支持BackgroundWorker报告异步任务进度的功能。
        worker.WorkerReportsProgress = true;

        // WorkerSupportsCancellation  是否支持异步取消操作
        worker.WorkerSupportsCancellation = true;

        // 三个事件
        // 1 DoWork: 做异步耗时的操作(调用RunWorkerAsync方法之后触发)
        worker.DoWork += Worker_DoWork;

        // 2 ProgressChange 进度发生变化的事件,WorkerReportsProgress属性true的时候触发
        worker.ProgressChanged += Worker_ProgressChanged;

        // 3 RWorkerCompleted 后台操作完成的时候触发,取消或者异常的时候都会触发
        worker.RunWorkerCompleted += Worker_RunWorkerCompleted;

    }

    //做异步任务的函数

    private void Worker_DoWork(object sender, DoWorkEventArgs e)
    {
        //模拟处理超时的操作
        Random rnd = new Random();
        for (int i = 0; i < 80; i++)
        {
            if (worker.CancellationPending) //判断用户是否取消了后台任务
            {
                e.Cancel = true; //取消后台任务
                return;
            }
            else
            {
                //耗时任务(文件读写,通讯、加载tb块)
                Thread.Sleep(rnd.Next(100, 1000)); //休眠100-1000ms之间,模拟耗时的

                //报告进度
                int progress = (int)Math.Round(((i + 1) / 80.0) * 100);
                progress = progress > 100 ? 100 : progress;

                worker.ReportProgress(progress);// 触发进度变化的事件

            }
        }

    }
    //加载进度的函数
    private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;// 把ReportProgress(progress)函数里面的参数传递过来,取出
    }

    //后台操作处理完的函数
    private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        this.BackColor = Color.Red;// 后台任务执行完之后的操作
    }

    //开始异步任务的按钮
    private void button1_Click(object sender, EventArgs e)
    {
        Console.WriteLine(worker.IsBusy);// backWrork是否是繁忙状态
        if (!worker.IsBusy) // 空闲状态下
        {
            worker.RunWorkerAsync();// 开始后台任务
        }
    }

    //取消异步任务的按钮
    private void button2_Click(object sender, EventArgs e)
    {
        if (worker.IsBusy) //非空闲状态下取消
        {
            worker.CancelAsync();//取消后台任务
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Csharp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值