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日

相关文章

  • 解决unity3d导入模型贴图材质丢失的问题

    关于解决Unity3D导入模型贴图材质丢失的问题,可以从以下几个方面入手: 方案一:检查模型资源文件 首先要检查一下模型的资源文件是否完整,包括模型本身、贴图、材质等资源是否都已经正确导入。 如果模型资源文件存在问题,需要重新导入或者重新下载安装包等方式解决。 方案二:手动贴图重建材质 如果模型资源文件没有问题,但是材质丢失,可以手动重建材质。 首先需要为模…

    C# 2023年6月3日
    00
  • .Net笔记:System.IO之Stream的使用详解

    .Net笔记: System.IO之Stream的使用详解 Stream的概念 Stream是System.IO命名空间下一个抽象类,它提供了一种用于读和写编码数据的通用视图。它可以作为抽象类来实现更特定类型的流,如FileStream或MemoryStream。 Stream的特性 下面是Stream的一些主要特性: Stream可以是只读、可写或可读写的…

    C# 2023年6月7日
    00
  • 使用 C# 动态编译代码和执行的代码

    使用 C# 动态编译代码和执行的完整攻略 简单介绍 在 C# 中,我们可以使用 CodeDomProvider 来动态编译代码并执行。CodeDomProvider 是一个可以根据指定文件扩展名和编译器参数来编译程序集的编译器。 示例1:动态编译代码并执行 以下是一个简单的示例,演示了如何使用 CodeDomProvider 对 C# 代码进行动态编译和执行…

    C# 2023年6月7日
    00
  • C#中的正则表达式双引号问题

    C#中的正则表达式中双引号问题,主要是因为C#语言本身使用双引号来定义字符串,而正则表达式中也常常需要使用双引号来定义某些模式。因此,在将正则表达式作为字符串处理时,需要注意双引号字符的转义问题。 1. 双引号的转义 在C#中,要在字符串中插入双引号字符,需要使用反斜杠(\)字符进行转义,例如: string str = "This is a \&…

    C# 2023年6月7日
    00
  • C#中多维数组[,]和交错数组[][]的区别

    C#中多维数组[,]和交错数组[][]的区别 C#中提供了两种不同类型的多维数组:多维数组和交错数组。它们的使用方法略有不同,下面分别进行具体讲解。 多维数组[,] 多维数组是一种具有两个或更多维的数组,使用[,]定义。例如: int[,] array = new int[3, 4]; 上述代码定义了一个3行4列的二维整数数组。 使用多维数组时,可以通过以下…

    C# 2023年5月15日
    00
  • C#导出Excel的示例详解

    C#导出Excel的示例详解 介绍 在实际的项目中,我们经常需要将数据导出到Excel表格中,以方便查阅和管理。C#作为一门强大的编程语言,在导出Excel方面也有非常不错的表现。本篇文章将详细讲解如何使用C#导出Excel表格。 准备工作 我们需要使用C#自带的OpenXML库来实现Excel的导出。在使用前,需要进行一些准备工作: 引入DocumentF…

    C# 2023年6月7日
    00
  • C#子线程执行完后通知主线程的方法

    Sure,关于“C#子线程执行完后通知主线程的方法”,目前主流的解决方法有以下几种: 1. 使用System.Threading.Tasks.Task机制 Tasks是.NET Framework中一种比传统线程更高效、更易于使用的并发编程模型。使用Task机制,可使线程的启动和执行过程简单高效,同时还可通过Task状态监视线程的执行情况,以及异步获取线程的…

    C# 2023年6月7日
    00
  • c# 值类型实例构造器

    C#值类型实例构造器 在C#中,值类型是一种基本数据类型,如int、double、char、bool等等。与引用类型不同,值类型的实例被存储在堆栈中,而不是在堆中。C#值类型实例构造器是一种特殊的方法,在值类型实例被创建时,它会被自动调用。本文将详细讲解C#值类型实例构造器的用法和示例。 构造器的概念和特点 构造器是一种特殊的方法,它用于初始化一个类的实例。…

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