首页
学习
活动
专区
圈层
工具
发布
50 篇文章
1
【愚公系列】2023年11月 WPF控件专题 Line控件详解
2
【愚公系列】2023年11月 WPF控件专题 2023秋招WPF高频面试题
3
【愚公系列】2023年11月 Winform控件专题 Label控件详解
4
【愚公系列】2023年11月 Winform控件专题 Button控件详解
5
【愚公系列】2023年11月 Winform控件专题 Form控件详解
6
【愚公系列】2023年11月 Winform控件专题 TextBox控件详解
7
【愚公系列】2023年11月 Winform控件专题 CheckBox控件详解
8
【愚公系列】2023年11月 Winform控件专题 RadioButton控件详解
9
【愚公系列】2023年11月 Winform控件专题 ComboBox控件详解
10
【愚公系列】2023年11月 Winform控件专题 RichTextBox控件详解
11
【愚公系列】2023年11月 Winform控件专题 ListBox控件详解
12
【愚公系列】2023年11月 Winform控件专题 CheckedListBox控件详解
13
【愚公系列】2023年11月 Winform控件专题 numericUpDown控件详解
14
【愚公系列】2023年11月 Winform控件专题 LinkLabel控件详解
15
【愚公系列】2023年11月 Winform控件专题 DateTimePicker控件详解
16
【愚公系列】2023年11月 Winform控件专题 NotifyIcon控件详解
17
【愚公系列】2023年11月 Winform控件专题 ContextMenuStrip控件详解
18
【愚公系列】2023年11月 Winform控件专题 Timer控件详解
19
【愚公系列】2023年11月 Winform控件专题 PictureBox控件详解
20
【愚公系列】2023年11月 Winform控件专题 Chart控件详解
21
【愚公系列】2023年11月 Winform控件专题 DataGridView控件详解
22
【愚公系列】2023年11月 Winform控件专题 TableLayoutPanel控件详解
23
【愚公系列】2023年11月 Winform控件专题 ProgressBar控件详解
24
【愚公系列】2023年11月 Winform控件专题 Panel控件详解
25
【愚公系列】2023年11月 Winform控件专题 FlowLayoutPanel控件详解
26
【愚公系列】2023年11月 Winform控件专题 GroupBox控件详解
27
【愚公系列】2023年11月 Winform控件专题 SplitContainer控件详解
28
【愚公系列】2023年11月 Winform控件专题 TabControl控件详解
29
【愚公系列】2023年11月 Winform控件专题 ToolTip控件详解
30
【愚公系列】2023年11月 Winform控件专题 MaskedTextBox控件详解
31
【愚公系列】2023年11月 Winform控件专题 MonthCalendar控件详解
32
【愚公系列】2023年11月 Winform控件专题 TreeView控件详解
33
【愚公系列】2023年11月 Winform控件专题 MenuStrip控件详解
34
【愚公系列】2023年11月 Winform控件专题 OpenFileDialog控件详解
35
【愚公系列】2023年11月 Winform控件专题 SaveFileDialog控件详解
36
【愚公系列】2023年12月 Winform控件专题 FontDialog控件详解
37
【愚公系列】2023年12月 Winform控件专题 ColorDialog控件详解
38
【愚公系列】2023年12月 Winform控件专题 FolderBrowserDialog控件详解
39
【愚公系列】2023年12月 Winform控件专题 StatusStrip控件详解
40
【愚公系列】2023年12月 Winform控件专题 ToolStrip控件详解
41
【愚公系列】2023年12月 Winform控件专题 HelpProvider控件详解
42
【愚公系列】2023年12月 Winform控件专题 ToolStripContainer控件详解
43
【愚公系列】2023年12月 Winform控件专题 BackgroundWorker控件详解
44
【愚公系列】2023年12月 GDI+绘图专题 图形图像编程基础
45
【愚公系列】2023年12月 GDI+绘图专题 图形图像的重绘
46
【愚公系列】2023年12月 GDI+绘图专题 颜色获取和图形绘制
47
【愚公系列】2023年12月 GDI+绘图专题 Point
48
【愚公系列】2023年12月 GDI+绘图专题 Rectangle
49
【愚公系列】2023年12月 GDI+绘图专题 Matrix
50
【愚公系列】2023年12月 GDI+绘图专题 Pen

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

🏆 作者简介,愚公搬代码 🏆《头衔》:华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,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属性并在异步操作中报告进度:

代码语言:csharp
复制
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属性:

代码语言:csharp
复制
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 类。

代码语言:csharp
复制
using System.ComponentModel;

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

代码语言:csharp
复制
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。这些事件将在后台线程中执行,并用于计算斐波那契数列、更新进度和显示结果。

代码语言:csharp
复制
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 的线程,并禁用按钮以防止用户重复点击。

代码语言:csharp
复制
private void button1_Click(object sender, EventArgs e)
{
    button1.Enabled = false; // 禁用按钮

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

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

代码语言:csharp
复制
private void button2_Click(object sender, EventArgs e)
{
    if (bgWorker.IsBusy)
    {
        bgWorker.CancelAsync();
    }
}

完整代码:

代码语言:csharp
复制
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;
        }
    }
}

我正在参与2023腾讯技术创作特训营第四期有奖征文,快来和我瓜分大奖!

下一篇
举报
领券