【愚公系列】2023年11月 Winform控件专题 BackgroundWorker控件详解

举报
愚公搬代码 发表于 2023/11/27 00:08:47 2023/11/27
【摘要】 🏆 作者简介,愚公搬代码🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物...

🏆 作者简介,愚公搬代码
🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,阿里云专家博主,腾讯云优秀博主,掘金优秀博主,51CTO博客专家等。
🏆《近期荣誉》:2022年CSDN博客之星TOP2,2022年华为云十佳博主等。
🏆《博客内容》:.NET、Java、Python、Go、Node、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、大数据、人工智能、U3D游戏、小程序等相关领域知识。
🏆🎉欢迎 👍点赞✍评论⭐收藏

🚀前言

Winform控件是Windows Forms中的用户界面元素,它们可以用于创建Windows应用程序的各种视觉和交互组件,例如按钮、标签、文本框、下拉列表框、复选框、单选框、进度条等。开发人员可以使用Winform控件来构建用户界面并响应用户的操作行为,从而创建功能强大的桌面应用程序。

🚀一、BackgroundWorker控件详解

BackgroundWorker控件是Windows Forms中提供的一个轻量级组件,用于在后台线程中执行耗时的操作,避免阻塞UI线程,提高应用程序的响应性能。BackgroundWorker控件通过在异步线程中执行操作,并在操作完成后在UI线程上引发事件来完成此目的。

BackgroundWorker控件提供了以下事件和方法,以方便在异步操作中实现进度报告、取消操作、完成操作等功能:

事件:

  • DoWork:异步线程执行操作的事件。
  • ProgressChanged:异步线程报告操作进度的事件。
  • RunWorkerCompleted:异步操作完成时引发的事件。

方法:

  • RunWorkerAsync:启动异步操作的方法。
  • CancelAsync:请求取消异步操作的方法。

使用BackgroundWorker控件时,需要注意以下几点:

  • 在DoWork事件中执行耗时的操作,不能调用UI线程上的控件,如需更新UI上的控件,需要在ProgressChanged事件中调用。
  • 在RunWorkerCompleted事件中发生的任何异常都会被视为未处理异常,并导致应用程序崩溃。
  • 如果需要在DoWork事件中定期检查是否已请求取消异步操作,可以使用CancellationPending属性,该属性为只读属性,如果已请求取消操作,则为true,否则为false。

🔎1.属性介绍

🦋1.1 WorkerReportsProgress

BackgroundWorker控件的WorkerReportsProgress属性用于指示是否支持异步报告进度。如果将其设置为true,则可以在异步操作中使用ReportProgress方法报告进度。如果设置为false,则不能使用ReportProgress方法,否则会引发InvalidOperationException异常。

WorkerReportsProgress属性的默认值为false。如果需要在异步操作中报告进度,则必须将其设置为true。

下面是一个示例,演示如何设置WorkerReportsProgress属性并在异步操作中报告进度:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    // 设置WorkerReportsProgress属性为true
    backgroundWorker1.WorkerReportsProgress = true;

    // 执行耗时的操作
    for (int i = 0; i <= 100; i++)
    {
        Thread.Sleep(50);
        // 报告进度
        backgroundWorker1.ReportProgress(i);
    }
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // 更新UI上的控件
    progressBar1.Value = e.ProgressPercentage;
}

private void button1_Click(object sender, EventArgs e)
{
    // 启动异步操作
    backgroundWorker1.RunWorkerAsync();
}

在这里插入图片描述

在上述示例中,需要在DoWork事件中将WorkerReportsProgress属性设置为true,以启用ReportProgress方法,然后在循环中调用ReportProgress方法报告进度。在ProgressChanged事件中更新UI上的进度条控件。

🦋1.2 WorkerSupportsCancellation

BackgroundWorker控件是一个可用于执行后台操作的组件。它提供了一个异步操作模型,可以允许后台线程执行操作,并在操作完成后通知前台线程。

WorkerSupportsCancellation属性是BackgroundWorker控件的一个属性,用于指示后台操作是否支持取消。当WorkerSupportsCancellation属性设置为true时,可以通过调用BackgroundWorker控件的CancelAsync方法来请求取消后台操作。

下面是一个简单的示例,演示如何在Winform中使用BackgroundWorker控件和WorkerSupportsCancellation属性:

private BackgroundWorker backgroundWorker1;

private void buttonStart_Click(object sender, EventArgs e)
{
    // 初始化BackgroundWorker控件
    backgroundWorker1.WorkerSupportsCancellation = true;
    // 启动异步操作
    backgroundWorker1.RunWorkerAsync();
}

private void buttonCancel_Click(object sender, EventArgs e)
{
    // 请求取消异步操作
    backgroundWorker1.CancelAsync();
}

// 后台操作方法
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    backgroundWorker1.WorkerReportsProgress = true;

    for (int i = 1; i <= 100; i++)
    {
        // 检查是否请求取消
        if (backgroundWorker1.CancellationPending)
        {
            e.Cancel = true;
            break;
        }

        // 模拟长时间操作
        Thread.Sleep(100);

        // 更新进度条
        backgroundWorker1.ReportProgress(i);
    }
}

// 异步操作完成方法
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled)
        MessageBox.Show("异步操作已取消!");
    else if (e.Error != null)
        MessageBox.Show("异步操作发生错误:" + e.Error.Message);
    else
        MessageBox.Show("异步操作已完成!");
}

在这里插入图片描述

在这个示例中,当点击“开始”按钮时,创建并启动BackgroundWorker控件,并在其中执行一个模拟的长时间操作。在操作执行过程中,每次更新进度条并检查是否请求取消。当点击“取消”按钮时,调用BackgroundWorker控件的CancelAsync方法来请求取消操作。当异步操作完成时,根据操作是否被取消或是否发生错误来显示相应的提示信息。

通过使用BackgroundWorker控件和WorkerSupportsCancellation属性,可以轻松实现异步操作的取消功能,提高应用程序的用户体验。

🔎2.常用场景

BackgroundWorker控件在Winform应用程序中的常用场景有:

  1. 长时间运行的任务:当需要执行耗时的操作时,比如读取大量数据、计算复杂算法、网络请求等,BackgroundWorker可以在后台执行,避免阻塞UI线程,提高用户体验。

  2. 操作进度条:在执行长时间运行的任务时,可以使用BackgroundWorker来更新进度条,让用户知道任务的进度和剩余时间。

  3. 异步处理问题:在Winform应用程序中,有时需要异步地执行某些操作,比如在窗口关闭时保存数据、进行数据同步等,BackgroundWorker可以帮助实现异步操作,避免阻塞UI线程。

  4. 实时更新UI:有些操作需要实时更新UI,比如显示传感器数据、播放音频等,BackgroundWorker可以在后台执行数据处理和更新UI,避免UI线程被阻塞。

🔎3.具体案例

以下是一个利用 BackgroundWorker 控件实现在后台线程中计算斐波那契数列,并将结果显示在 UI 上。

首先,在 UI 界面中添加一个 Label 控件用于显示结果,一个 Button 控件作为触发事件的按钮,以及一个 BackgroundWorker 控件。

在代码中,先引入 System.ComponentModel 命名空间,这个命名空间包含了 BackgroundWorker 类。

using System.ComponentModel;

在类中定义全局变量和 BackgroundWorker 对象:

public partial class Form1 : Form
{
    private int n = 10; // 计算斐波那契数列的项数
    private long[] fib; // 保存斐波那契数列的数组
    private BackgroundWorker bgWorker; // BackgroundWorker 对象

    public Form1()
    {
        InitializeComponent();

        // 创建 BackgroundWorker 对象
        bgWorker = new BackgroundWorker();

        // 设置 WorkerReportsProgress 和 WorkerSupportsCancellation 属性
        bgWorker.WorkerReportsProgress = true;
        bgWorker.WorkerSupportsCancellation = true;

        // 注册事件处理程序
        bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
        bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
        bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
    }

    // ...
}

接下来,定义 BackgroundWorker 的三个事件处理程序,分别是 DoWork、ProgressChanged 和 RunWorkerCompleted。这些事件将在后台线程中执行,并用于计算斐波那契数列、更新进度和显示结果。

private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    // 计算斐波那契数列
    fib = new long[n];
    fib[0] = 0;
    fib[1] = 1;

    for (int i = 2; i < n; i++)
    {
        if (bgWorker.CancellationPending)
        {
            e.Cancel = true;
            return;
        }

        fib[i] = fib[i - 2] + fib[i - 1];
        int progress = (int)(((double)i / n) * 100);
        bgWorker.ReportProgress(progress);
        Thread.Sleep(100); // 模拟耗时操作
    }
}

private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // 显示进度条
    progressBar1.Value = e.ProgressPercentage;
}

private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // 显示结果
    if (e.Cancelled)
    {
        label1.Text = "计算取消";
    }
    else if (e.Error != null)
    {
        label1.Text = "计算错误";
    }
    else
    {
        label1.Text = "结果:\n" + string.Join(", ", fib);
    }

    // 恢复按钮状态
    button1.Enabled = true;
}

在按钮的 Click 事件处理程序中,开启 BackgroundWorker 的线程,并禁用按钮以防止用户重复点击。

private void button1_Click(object sender, EventArgs e)
{
    button1.Enabled = false; // 禁用按钮

    // 开启线程
    if (!bgWorker.IsBusy)
    {
        bgWorker.RunWorkerAsync();
    }
}

最后,添加一个取消计算的按钮,并在其 Click 事件处理程序中调用 CancelAsync() 方法取消后台线程的计算。

private void button2_Click(object sender, EventArgs e)
{
    if (bgWorker.IsBusy)
    {
        bgWorker.CancelAsync();
    }
}

完整代码:

using System;
using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;

namespace BackgroundWorkerExample
{
    public partial class Form1 : Form
    {
        private int n = 10; // 计算斐波那契数列的项数
        private long[] fib; // 保存斐波那契数列的数组
        private BackgroundWorker bgWorker; // BackgroundWorker 对象

        public Form1()
        {
            InitializeComponent();

            // 创建 BackgroundWorker 对象
            bgWorker = new BackgroundWorker();

            // 设置 WorkerReportsProgress 和 WorkerSupportsCancellation 属性
            bgWorker.WorkerReportsProgress = true;
            bgWorker.WorkerSupportsCancellation = true;

            // 注册事件处理程序
            bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
            bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
            bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            button1.Enabled = false; // 禁用按钮

            // 开启线程
            if (!bgWorker.IsBusy)
            {
                bgWorker.RunWorkerAsync();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (bgWorker.IsBusy)
            {
                bgWorker.CancelAsync();
            }
        }

        private void bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            // 计算斐波那契数列
            fib = new long[n];
            fib[0] = 0;
            fib[1] = 1;

            for (int i = 2; i < n; i++)
            {
                if (bgWorker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }

                fib[i] = fib[i - 2] + fib[i - 1];
                int progress = (int)(((double)i / n) * 100);
                bgWorker.ReportProgress(progress);
                Thread.Sleep(100); // 模拟耗时操作
            }
        }

        private void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // 显示进度条
            progressBar1.Value = e.ProgressPercentage;
        }

        private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // 显示结果
            if (e.Cancelled)
            {
                label1.Text = "计算取消";
            }
            else if (e.Error != null)
            {
                label1.Text = "计算错误";
            }
            else
            {
                label1.Text = "结果:\n" + string.Join(", ", fib);
            }

            // 恢复按钮状态
            button1.Enabled = true;
        }
    }
}

在这里插入图片描述


🚀感谢:给读者的一封信

亲爱的读者,

我在这篇文章中投入了大量的心血和时间,希望为您提供有价值的内容。这篇文章包含了深入的研究和个人经验,我相信这些信息对您非常有帮助。

如果您觉得这篇文章对您有所帮助,我诚恳地请求您考虑赞赏1元钱的支持。这个金额不会对您的财务状况造成负担,但它会对我继续创作高质量的内容产生积极的影响。

我之所以写这篇文章,是因为我热爱分享有用的知识和见解。您的支持将帮助我继续这个使命,也鼓励我花更多的时间和精力创作更多有价值的内容。

如果您愿意支持我的创作,请扫描下面二维码,您的支持将不胜感激。同时,如果您有任何反馈或建议,也欢迎与我分享。

![在这里插入图片描述](https://img-blog.csdnimg.cn/e06a317e89694a23ad89d2c59538c3a1.jpeg#pic_center =450x300)

再次感谢您的阅读和支持!

最诚挚的问候, “愚公搬代码”

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。