BackgroudWork的详细用法,实例

news2024/11/28 19:29:58


一、什么是BackgroudWorker?


    1、简言
        backgroudworkd就是一个异步单线程,专门为入门级人员开发的。还可以显示进度条。操作简单实用,属于老技术。
        注意:如果调用两次这个线程,将会出错。
        
    
    2、backgroudworker介绍
        BackgroundWorker 是一个在 .NET Framework 中提供的用于简化多线程编程的辅助类。它允许在后台线程中执行耗时的操作,同时在主线程中更新用户界面。BackgroundWorker 提供了一种简单的方法来处理异步操作,避免阻塞主线程,以提高用户界面的响应性。

        使用 BackgroundWorker 的一般步骤(下面是动态生成该控件,拖放控件只看3-5步):

        (1)实例化一个 BackgroundWorker 对象。
        (2)注册事件处理程序,如 DoWork(处理耗时操作)、ProgressChanged(报告进度更新)和 RunWorkerCompleted(在操作完成后进行清理等处理)。
        (3)在 DoWork 事件处理程序中执行需要在后台线程中完成的操作。可以使用 ReportProgress 方法报告进度。
        (4)在 ProgressChanged 事件处理程序中更新界面,以反映进度的变化。
        (5)在 RunWorkerCompleted 事件处理程序中进行清理操作并处理操作的结果。

        通过 BackgroundWorker,你可以简化异步编程,使得处理耗时操作和更新用户界面变得更加方便。然而,需要注意的是,BackgroundWorker 是一个较为旧的技术,在更高级的异步编程场景中,可能需要使用 Task、async/await 等更为现代的机制和模式。
            
    3、动态生成的控件与编写前拖放的控件,两者在资源耗费上哪个更节约?
        动态生成的控件与编写前拖放的控件,两者在资源耗费上没有明确的答案,取决于具体的实现方式和使用场景。
        动态生成的控件通常是在运行时根据需求动态创建的,这样可以根据实际需要灵活地生成控件,避免了不必要的资源浪费。然而,动态生成控件需要在运行时进行额外的计算和内存分配,可能会增加一定的开销。
        编写前拖放的控件通常是在设计时通过可视化编辑器进行的,可以直接在界面上进行拖放和布局,相对来说更加直观和方便。但是,编写前拖放的控件可能会在设计时就占用一定的资源,尤其是对于复杂的界面和大量的控件。
        因此,要选择哪种方式需要根据具体的需求和场景来决定。如果界面较为简单,控件数量有限,且需要频繁动态改变控件的情况下,动态生成的控件可能更加节约资源。如果界面复杂,控件数量较多且固定,且不需要频繁改变控件的情况下,编写前拖放的控件可能更加方便和节约资源。

    4、一个 BackgroundWorker 只能同时启动一次 RunAsync?
        是的,一个 BackgroundWorker 只能同时启动一次 RunAsync。 BackgroundWorker 是用于在后台线程执行长时间运行的任务的组件,它提供了一种简单的方式来执行异步操作并在完成后返回结果。
        当调用 BackgroundWorker 的 RunAsync 方法时,它会在后台线程中执行指定的操作。在操作完成之前,不能再次调用 RunAsync 方法。如果尝试再次调用 RunAsync 方法,会抛出 InvalidOperationException 异常。
        如果需要同时执行多个异步操作,可以考虑使用 Task 类或其他多线程机制来实现。 Task 类提供了更灵活和强大的异步编程模型,可以同时启动多个任务并进行管理。
    
    5、BackgroundWorker的各事件在什么线程中执行?
        DoWork 事件处理程序是在后台线程中执行的,用于处理耗时的操作。这使得主线程可以保持响应,并且不会被阻塞。
        
        BackgroundWorker 类中的ProgressChanged 和 RunWorkerCompleted由主线程发起和处理的。
        
        ProgressChanged 事件用于报告进度的更新,
        RunWorkerCompleted 事件在后台操作完成后触发,
        ReportProgress 方法用于在 DoWork 中报告进度
        CancelAsync 方法用于请求取消操作。
        
        eportProgress 方法是在 DoWork 方法中由后台线程发起的。它用于向主线程报告进度信息。

    6、前台线程,后台线程,主线程,子线程,同步线程,异步线程
        前台线程是指会阻塞应用程序关闭的线程,它会等待所有前台线程执行完毕后才会终止应用程序。在C#中,Thread 类创建的线程默认是前台线程。
        后台线程是一种在后台执行的线程,它与主线程(前台线程)相对。后台线程不会阻止应用程序的退出,当所有的前台线程结束时,后台线程会自动终止。后台线程通常用于执行一些不需要与用户界面交互的任务,例如执行耗时的计算、文件操作、网络请求等。它们可以在应用程序的后台默默地执行,而不会阻塞用户界面的响应。
        主线程一般指调用线程,即运行最开始的线程,比如form1的UI线程,或控制台的Main(),子线程是相对于主线程而说,由主线程启动的另一个线程一般叫子线程(父生子)。
        
        异步线程和同步线程的区别在于线程之间的关系和执行方式。异步线程是独立运行的,彼此并行执行,而同步线程需要与其他线程协作,相互等待或同步执行。
        异步线程是指在应用程序中同时执行的线程,它们可以与当前线程并行执行,彼此独立运行,并且它们的执行顺序和完成时间不受当前线程的干预。异步线程通常用于执行耗时的操作,以避免阻塞当前线程。

        同步线程是指按照一定的顺序执行的线程,它们需要与当前线程协作,相互等待或同步执行。同步线程通常用于保证线程安全性或确保任务的有序执行。

        异步和同步的区别在于线程之间的关系和执行方式:

        异步线程是独立运行的,彼此之间没有干预,它们可以并行执行,不需要等待其他线程的完成。
        同步线程需要与其他线程协作,它们可能会相互等待或同步执行,以确保任务的有序执行或线程安全性。
        异步线程通常用于执行耗时的操作,以避免阻塞当前线程,提高应用程序的响应性。
        同步线程通常用于保证线程安全性,确保多个线程对共享资源的访问不会发生冲突。

        Thread 可以用于创建前台线程或后台线程,它的行为取决于线程的创建方式和所在的上下文。在 Task 中使用的 Thread 是后台线程,它是异步执行的,不会阻塞主线程。而在 UI 主线程中使用的 Thread 是前台线程,如果阻塞主线程,会导致界面卡顿或无响应。
        
        在 Task 中使用的 Thread 是一个后台线程,它是异步执行的。在这种情况下,Task 会创建一个新的线程来执行异步操作,而主线程可以继续执行其他任务。这个后台线程与主线程是独立的,它不会阻塞主线程的执行。

        而在 UI 主线程中使用的 Thread 是一个前台线程,它会阻塞主线程的执行。在 UI 应用程序中,主线程通常是用于处理用户界面的线程,如果在主线程中执行耗时操作,会导致界面卡顿或无响应。因此,为了保持用户界面的流畅性,通常会将耗时操作放在后台线程中执行。

        注意,如果在 UI 主线程中使用 Thread.Join() 方法等待同步线程的执行,那么主线程会被阻塞,直到同步线程执行完毕。这种情况下,同步线程会阻塞当前线程,使得当前线程成为同步线程。
        
        BackgroundWorker 中的子线程就是后台线程。后台线程是一种在应用程序运行期间在后台执行的线程,与主线程并行执行,不会阻塞主线程的执行。
        BackgroundWorker 创建的子线程默认是后台线程,它在后台执行长时间运行的操作,而不会阻塞主线程。这使得主线程可以继续响应用户界面的交互,而不会出现假死的情况。
        总结,后台线程是一种异步线程的实现方式,它可以在后台执行长时间运行的操作,而不会阻塞主线程的执行。异步线程可以是后台线程或前台线程,而后台线程是一种特定的异步线程类型。
        
    7、为什么常说异步操作,而不说异步线程?
        为了使编程更简单,刻意避免使用底层线程池或异步线程的概念,而使用更高级抽象封装的概念,故说异步操作,不说异步线程。
        Task 是对异步操作的高级封装,它提供了一种更高级的编程模型,使得异步编程变得更加简单和易于理解。通过使用 Task,我们可以将异步操作的执行过程和结果进行抽象和封装,而不需要直接操作线程。

        Task 的设计目的是为了让开发者能够更方便地编写异步代码,而不需要过多地关注底层线程的细节。它提供了一系列的方法和属性,用于管理异步操作的状态、处理异常、获取结果等。开发者可以通过使用这些方法和属性,来编写和管理异步操作的执行逻辑。

        通过使用 Task,开发者可以将复杂的异步操作分解为多个小任务,并通过任务之间的依赖关系来组织和管理这些任务。这样可以使得异步编程更加直观和易于理解,避免了直接操作线程所带来的复杂性和困扰。

        因此,使用 Task 可以让开发者更轻松地入门和使用异步编程,而不需要深入了解底层线程的细节和复杂性。它提供了一种更高级的抽象和概念,使得异步编程变得更加易于理解和使用。

二、BackgoundWorker实例


    1、一个backgroudnworker控件,button,textbox,label。界面如下
        

        
        程序:

        private void BtnRun_Click(object sender, EventArgs e)
        {
            backgroundWorker1.WorkerReportsProgress = true;//要显示进度
            label1.BackColor = Color.Transparent;
            label1.Text = "0";
            backgroundWorker1.RunWorkerAsync();
            // backgroundWorker1.RunWorkerAsync("Hello world");//a
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)//子线程
        {
            //string s = e.Argument as string;//b
            for (int i = 0; i < 101; i++)
            {
                Thread.Sleep(100);
                backgroundWorker1.ReportProgress(i);//c
                ShowMsg(i.ToString());
                //ShowMsg(i.ToString()+s );//d
            }
            e.Result = "线程中的信息";//e
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)//主线程
        {
            progressBar1.Value = e.ProgressPercentage;//f
            label1.Text = e.ProgressPercentage.ToString();
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)//主线程
        {
            ShowMsg("程序执行完成。");
            ShowMsg(e.Result.ToString());//g
        }

        private void ShowMsg(string s)
        {
            if (TxtInfo.InvokeRequired)
            { BeginInvoke(new Action(() => { TxtInfo.AppendText($"{s} \r\n"); })); }
            else
            { TxtInfo.AppendText($"{s} \r\n"); }
        }


        
    2、RunWorkerAsync()是启动子线程,可以带参数见a处
        参数在子线程通过DoWorkEventArgs e传递过来,用e.Argument来转换,在b处进行变换,包括以数组形式的方式传递参数。
        在d处接收数据,或处理数据。
    
    3、c处报告进度。
        ReportProgress 方法的 progressPercentage 参数应该是一个介于 0 到 100 之间的整数值,用于表示进度的百分比。例如,通过调用 backgroundWorker1.ReportProgress(50),您可以向 ProgressChanged 事件处理程序报告任务完成了一半。
        从 DoWork 事件处理程序中调用 ReportProgress 方法可以将更新的进度信息传递给 ProgressChanged 事件处理程序。然后,您可以在 ProgressChanged 事件处理程序中更新进度条或执行其他操作以反映操作的进度。
        在c处传出数据,在ProgressChanged事件的ProgressChangedEventArgs e中接收,通过在f处的e.ProgressPercentage提取数据(object)。
        
    4、e处的Result属性是一个暂存仓库,相当于一个公有变量,把子线程中的值传递到主线程,比如g处,也可以在ProgressChanged事件中传递。
        
        
    5、简言之:如果没有必要,尽量不用backgroundworker这个老办法。
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/975781.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

centos7下docker设置新的下载镜像源并调整存放docker下载镜像的仓库位置

目录 1.设置镜像源 2.调整存放下载镜像的仓库位置 1.设置镜像源 在 /etc/docker下创建一个daemon.json文件。在json中下入 "registry-mirrors": ["https://docker.mirrors.ustc.edu.cn/"] 完成配置 加载配置 systemctl daemon-reload 重启docker sy…

医学影像工作站PACS系统源码,医院PACS系统源码

医学影像(PACS)系统主要进行病人信息和影像的获取、处理、存储、调阅、检索、管理&#xff0c;并通过网络向全院提供病人检查影像及诊断报告&#xff1b;各影像科室之间共享不同设备的病人检查影像及诊断报告&#xff1b;在诊断工作站上&#xff0c;调阅HIS中病人的其它信息&am…

企业架构LNMP学习笔记13

上线商城项目&#xff1a; 1&#xff09;上传项目文件到数据库&#xff1a; 入口文件位置的设计是为了让应用部署更安全&#xff0c;public目录为web可访问目录&#xff0c;其他的文件都可以放到非web访问目录下面。 nginx 默认访问index.html。没有index.html&#xff0c;就会…

软路由ip的优势与劣势:了解其适用场景和限制

在网络技术的快速发展中&#xff0c;软路由IP作为一种灵活且功能强大的网络设备&#xff0c;越来越受到人们的关注。然而&#xff0c;正如任何技术一样&#xff0c;软路由IP也有其优势和劣势。本文将深入探讨软路由IP的优势、劣势以及其适用场景和限制&#xff0c;帮助你更好地…

【回眸】牛客网刷刷刷!(八)——中断专题

目录 前言 1、在CortexM内核中&#xff0c;当系统响应一个中断时 2、用与非门和或非门可以实现其他基本门电路。进而实现任何逻辑电路 3、cpu interface提供了功能包含 4、以Cortex-M3内核为例&#xff0c;如果某个中断在得到响应之前&#xff0c;其请求信号以若干的脉冲的…

kafka-- 安装kafka manager及简单使用

一 、安装kafka manager 管控台&#xff1a; # 安装kafka manager 管控台&#xff1a; ## 上传 cd /usr/local/software ## 解压 unzip kafka-manager-2.0.0.2.zip -d /usr/local/ cd /usr/local/kafka-manager-2.0.0.2/conf vim /usr/local/kafka-manager-2.0.0.2/conf/appl…

MySql学习笔记03——DQL(数据查询)基本命令

DQL 导入数据 首先使用use database进入数据库中&#xff0c;然后使用命令 source D:\mysql_learning\mysql_learning\document\bjpowernode.sql注意文件名不能有双引号&#xff0c;命令结尾没有分号。 SQL脚本 .sql文件是SQL脚本文件&#xff0c;它里面的内容都是SQL语句…

个人炒伦敦银方法大公开

个人炒伦敦银的方法与机构投资者炒这个品种的方法是有不同的&#xff0c;但是双方可能会借鉴一些相同的分析工具&#xff0c;比方说有的机构可能也会使用技术分析&#xff0c;当然&#xff0c;个人投资者对技术分析这个词更是不会陌生。今天我们就从个人投资者的角度出发&#…

计算机竞赛 基于深度学习的人脸识别系统

前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的人脸识别系统 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-senior/…

8、异常机制---- 8.1 Error和Exception

8、异常机制 8.1 Error和Exception 什么是异常 在实际工作中&#xff0c;遇到的情况不可能是非常完美的。比如&#xff1a;你写的某个模块&#xff0c;用户输入不一定符合你的要求、你的程序要打开某个文件&#xff0c;这个文件可能不存在或者文件格式不对&#xff0c;你要读…

23. 带旋转的数独游戏

题目 Description 数独是一个基于逻辑的组合数字放置拼图&#xff0c;在世界各地都很受欢迎。 在这个问题上&#xff0c;让我们关注 网格的拼图&#xff0c;其中包含 个区域。 目标是用十六进制数字填充整个网格&#xff0c;即 &#xff0c;以便每列&#xff0c;每行和每个区…

ABB机器人20032转数计数器未更新故障报警处理方法

ABB机器人20032转数计数器未更新故障报警处理方法 ABB的机器人上面安装有电池,需要定期进行更换(正常一年换一次),如果长时间不更换,电量过低,就会出现转数计数器未更新的报警,各轴编码器的位置就会丢失,在更换新电池后,需要更新转数计数器。 具体步骤如下: 先用手动…

泛微OA流程表单中代码块获取URL的参数

获取URL的参数 需要编辑自定义函数 function getUrlParam(key){var url decodeURI(window.location.href);var paramMap {};var paramStr url.split("?")[2];if (paramStr && paramStr ! "") {var paramStrArr paramStr.split("&&qu…

客户忠诚度和保留率:不良方法的陷阱

良好的客户忠诚度和保留策略是任何电子商务业务成功的关键因素。但当出现问题时会发生什么&#xff1f;您可以采取哪些措施来鼓励忠诚度并减少客户流失&#xff1f;继续阅读以了解不良客户忠诚度和保留实践的后果。 忠诚度和保留率低下的后果 客户不满意和高流失率 客户忠诚…

直播软件app开发中的AI应用及前景展望

在当今数字化时代&#xff0c;直播市场蓬勃发展&#xff0c;而直播软件App成为人们获取实时信息和娱乐的重要渠道。随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;直播软件App开发正逐渐融入AI的应用&#xff0c;为用户带来更智能、更个性化的直播体验。 …

什么是高压放大器

高压放大器是一种用于放大高电压信号的电子设备。它主要用于需要处理高电压信号的应用&#xff0c;如电力系统、医疗设备、科学研究以及工业和实验室实验等领域。下面将详细介绍高压放大器的原理、特点和应用。 高压放大器的原理基于电子放大技术&#xff0c;通过输入信号放大电…

国腾GM8284DD 将高速串行 LVDS 信号解码为并行 TTL 数据

国腾GM8284DD 1.描述&#xff1a; GM8284C 型 28 位可编程数据选通接收器主要用于视频/图像传输中的接收部分&#xff0c;实现 的功能是将高速串行 LVDS 信号解码为并行 TTL 数据&#xff0c;完成数据的解码功能。该器件可将 4 对串行 LVDS 差分信号在时钟信号作用下…

Java 加了@PreAuthorize注解的接口在Postman中访问

1. 首先&#xff0c;你需要获取一个有效的用户token&#xff0c;该token应包含了相应的接口权限。你可以通过登录或其他身份验证方式来获取token。2. 打开Postman&#xff0c;并确保已选择正确的HTTP方法&#xff08;GET、POST等&#xff09;。3. 在请求的Headers部分&#xff…

【TypeScript学习】—面向对象(四)

【TypeScript学习】—面向对象&#xff08;四&#xff09; 一、面向对象 二、类 三、构造方法 class Dog{name:string;age:number;//构造函数constructor(name:string,age:number){this.namename;this.ageage;}bark(){//在方法中可以通过this来表示当前调用方法的对象//this表…

数据结构零基础入门篇(C语言实现)

前言&#xff1a;数据结构属于C学习中较难的一部分&#xff0c;对应学习者的要求较高&#xff0c;如基础不扎实&#xff0c;建议着重学习C语言中的指针和结构体&#xff0c;万丈高楼平地起。 一&#xff0c;链表 1&#xff09;单链表的大致结构实现 用C语言实现链表一般是使…