C# BackgroundWorker用法详解

我们来详细讲解一下C#中的BackgroundWorker用法。

一、BackgroundWorker 是什么?

在C#中,BackgroundWorker是一个多线程组件,用于在后台执行一个操作并在主界面上更新相应的进度。它避免了在主线程中直接执行操作而引起的冻结UI界面的问题。

二、BackgroundWorker 的声明

我们使用 BackgroundWorker,需要在代码中添加一个 BackgroundWorker 控件。在 Visual Studio 中,您可以使用工具箱中的控件添加 BackgroundWorker,也可以使用设计器将其添加到表单中。

using System.ComponentModel;

namespace MyApplication
{
    public class MyClass
    {
        BackgroundWorker backgroundWorker;

        public MyClass()
        {
            backgroundWorker = new BackgroundWorker();
            backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
            backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
            backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
            backgroundWorker.WorkerReportsProgress = true;  
        }
    }
}

这个代码片段中,我们首先在类中声明了 BackgroundWorker 对象。我们还初始化了 backgroundWorker 对象并指定了三个事件处理程序。

  • DoWork: 当调用 RunWorkerAsync 方法时,这个事件处理程序将异步执行。
  • RunWorkerCompleted: 这个事件处理程序在异步操作完成并结束时调用。
  • ProgressChanged: 这个事件处理程序在异步操作执行并更改了进度报告时调用。

您还可以在构造函数中设置 WorkReportsProgress 属性为 true,以便在异步操作执行时能够报告进度。

三、BackgroundWorker 的常用方法和属性

BackgroundWorker 有以下常用方法和属性:

  • DoWorkEventArgs.Argument 属性:获取指定异步任务的参数。通过这个属性,我们可以向异步任务传递参数。
  • BackgroundWorker.RunWorkerAsync 方法:启动异步操作。
  • BackgroundWorker.CancellationPending 属性:获取异步操作是否应被取消的值。
  • BackgroundWorker.CancelAsync 方法:请求取消异步操作。
  • BackgroundWorker.ReportProgress 方法:报告异步操作的进度。

四、BackgroundWorker 的使用示例

示例1:异步操作,可取消

假设我们要执行一个耗时的操作,这里使用一个简单的循环。因为循环执行时间较长,我们需要在一个单独的线程中执行,以确保应用程序在执行操作时不会被冻结。

这里我们以一个计数器为例,每100ms加1,达到10时程序结束。

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    int total = (int)e.Argument;
    int count = 0;
    while (count < total)
    {
        if (worker.CancellationPending)
        {
            e.Cancel = true;
            break;
        }
        Thread.Sleep(100);
        count++;
        int progress = (int)((double)count / total * 100);
        worker.ReportProgress(progress, count);
    }
}

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled)
    {
        MessageBox.Show("操作被取消");
    }
    else if (e.Error != null)
    {
        MessageBox.Show("操作出现错误: " + e.Error.Message);
    }
    else
    {
        MessageBox.Show("操作完成");
    }
}

private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar.Value = e.ProgressPercentage;
    label.Text = "计数:" + e.UserState.ToString();
}

private void btnStart_Click(object sender, EventArgs e)
{
    int count = 10;
    if (int.TryParse(textBox.Text, out count))
    {
        if (!backgroundWorker.IsBusy)
        {
            btnStart.Enabled = false;
            btnCancel.Enabled = true;
            progressBar.Value = 0;
            label.Text = "计数:0";
            backgroundWorker.RunWorkerAsync(count);
        }
    }
    else
    {
        MessageBox.Show("请输入一个数字");
    }
}

private void btnCancel_Click(object sender, EventArgs e)
{
    if (backgroundWorker.IsBusy)
    {
        btnCancel.Enabled = false;
        backgroundWorker.CancelAsync();
    }
}

在这个示例中,我们使用 DoWork 事件完成循环操作。当 BackgroundWorker 的 CancellationPending 属性设置为 true 时,我们可以结束操作。 ProgressChanged 事件可以显示操作的当前进度,因此您可以监视操作的进程。

RunWorkerCompleted 事件将会调用在后台线程上执行的异步操作执行完成时调用的事件处理程序。 在事件处理程序中,我们可以检查 IsCanceled 属性是否为 true,以判断操作是正常结束还是被取消。

示例2:使用异步操作和进度报告

下一个示例仍然是异步操作,但由于计算不同,我们需要一种不同的方法来计算进度。在这个示例中,我们计算质数。正在计算质数时,线程睡眠1ms,以便其他程序继续运行。该计算迭代10,000, 因此,我们需要对已完成的百分比进行测量。

void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;
    int count = 0;
    for (int i = 2; i <= 10000; i++)
    {
        if (worker.CancellationPending)
        {
            e.Cancel = true;
            break;
        }

        bool isPrime = true;
        for (int j = 2; j < i; j++)
        {
            if (i % j == 0)
            {
                isPrime = false;
                break;
            }
        }

        if (isPrime)
        {
            count++;
            double percentage = (double)count / (double)10000 * 100;
            worker.ReportProgress((int)Math.Floor(percentage), count);
        }

        Thread.Sleep(1);
    }
}

void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar.Value = e.ProgressPercentage;
    labelPercentage.Text = e.ProgressPercentage.ToString() + "%";
    labelCount.Text = e.UserState.ToString();
}

void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Cancelled)
    {
        MessageBox.Show("质数计算被取消。");
    }
    else if (e.Error != null)
    {
        MessageBox.Show("质数计算异常: " + e.Error.Message);
    }
    else
    {
        labelCount.Text = "质数总共为:" + e.Result.ToString();
        MessageBox.Show("质数计算已完成!");
    }
}

void buttonStart_Click(object sender, EventArgs e)
{
    buttonStart.Enabled = false;
    buttonCancel.Enabled = true;
    progressBar.Value = 0;
    labelPercentage.Text = "0%";
    labelCount.Text = "总数为:0";
    backgroundWorker.RunWorkerAsync();
}

void buttonCancel_Click(object sender, EventArgs e)
{
    if (backgroundWorker.IsBusy)
    {
        backgroundWorker.CancelAsync();
    }
}

在这个示例中,使用异步操作计算质数,并使用一个进度条显示操作的进度。当 BackgroundWorker 的 ReportProgress 方法被调用时,ProgressChanged 事件就会触发, 其中, ReportProgress 用来实现异步报告进度,可以带有一个当前进度百分比,和一个可选的用户状态对象,以显示进度。 运行完成后,我们会调用 RunWorkerCompleted 事件处理程序,它在异步操作运行并完成时调用。在事件处理程序中,我们可以检查 IsCanceled 属性是否为 true,以判断操作是正常结束还是被取消。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# BackgroundWorker用法详解 - Python技术站

(0)
上一篇 2023年5月15日
下一篇 2023年5月15日

相关文章

  • 基于C#实现语音识别功能详解

    基于C#实现语音识别功能详解 简介 语音识别是目前非常流行的人机交互方式之一,也有很多应用场景,诸如:车载音响、语音助手、智能家居等。本文将介绍如何使用C#实现语音识别功能。 准备工作 为实现语音识别功能,我们需要引入第三方库——Microsoft Speech SDK。首先需要前往Microsoft官网下载安装SDK,地址:https://www.micr…

    C# 2023年5月15日
    00
  • 关于C#中的Invoke示例详解

    对于关于C#中的Invoke示例详解,我们可以按照以下步骤进行: 1. 什么是Invoke 在C# 中,Invoke是一个委托的方法,当我们使用多线程访问 UI 元素时,就需要使用Invoke。因为大多数的UI组件是跨线程的,而直接对线程不安全的UI组件进行操作会导致线程异常或UI操作的错误。 2. Invoke的使用场景及语法 使用Invoke的典型场景是…

    C# 2023年5月31日
    00
  • 一步步打造简单的MVC电商网站BooksStore(1)

    我来为您讲解一下“一步步打造简单的MVC电商网站BooksStore(1)”的完整攻略。 概述 本文主要是为了介绍如何使用PHP语言和MVC架构模式搭建一个简单的电商网站BooksStore。通过本文,您将会了解到如何设计和实现一个基于MVC架构的网站,并且了解到如何通过简单的代码实现用户登录、商品浏览、商品购买等功能。 MVC架构模式 MVC是一种软件架构…

    C# 2023年5月31日
    00
  • C# jpg缩略图函数代码

    下面详细讲解一下“C# jpg缩略图函数代码”的完整攻略。 简介 在web开发中,我们通常需要对图片进行缩略操作以提升页面加载速度和用户的浏览体验。下面介绍一下如何使用C#代码实现对jpg格式的图片进行缩略操作。 步骤 第一步:引用命名空间 首先需要引用命名空间 System.Drawing,该命名空间提供了在图像操作方面非常强大的支持。 using Sys…

    C# 2023年6月7日
    00
  • C#实现排序的代码详解

    首先,我们需要了解排序算法的基本概念和分类。排序是将一组混乱的元素按照某种规则进行排列的过程,常见的排序算法有冒泡排序、选择排序、插入排序、快速排序、归并排序等。其中,冒泡排序和插入排序适用于小规模的数据排序,而快速排序、归并排序则适用于大规模的数据排序。 接下来,我们以C#语言为例,讲解几种排序算法的实现步骤。 冒泡排序 冒泡排序是一种简单的排序算法,它的…

    C# 2023年5月31日
    00
  • 在C#中对TCP客户端的状态封装详解

    对TCP客户端的状态进行封装,可以提高代码的可维护性和可读性,方便后期的代码扩展和优化。在C#中,可以使用枚举类型和委托来实现对TCP客户端的状态封装。 1、枚举类型实现TCP客户端状态封装 使用枚举类型可以定义TCP客户端的连接状态、发送状态、接收状态等,用于标识TCP客户端当前所处的状态,同时可用于状态转换的判断。示例代码如下: public enum …

    C# 2023年5月15日
    00
  • AutoCAD二次开发系列教程01-如何在AutoCAD中输出Hello World

    目录 01项目环境准备 02代码示例 03输出示例 04总结 05源码地址 01项目环境准备 A.开发使用的软件:AutoCAD2016、VisualStudio2022 B.建立依赖的本地库(提前从AutoCAD软件安装目录拷贝开发时需要使用的库,如:accoremgd.dll) C.创建新的类库(.Net Framework),注意不同AutoCAD版本…

    C# 2023年5月5日
    00
  • C#中可枚举类型详解

    C#中可枚举类型详解 概述 C#中的枚举类型是一种特殊的值类型,用于定义一组相关的命名常量。枚举类型的成员可以是数字常量、字符串常量等,它为开发人员提供了一种更加方便、更加具有可读性和可维护性的编程方式。 定义枚举类型 在C#中定义枚举类型非常简单,只需要使用enum关键字即可。 enum WeekDay { Monday, Tuesday, Wednesd…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部