(C#)多线程-BackgroundWorker组件

简介:
BackgroundWorker组件
在VS2005中添加了BackgroundWorker组件,该组件在多线程编程方面使用起来非常方便,然而在开始时由于没有搞清楚它的使用机制,走了不少的弯路,现在把我在使用它的过程中的经验与诸位分享一下。
        BackgroundWorker类中主要用到的有这列属性、方法和事件:
        重要属性:
        1、CancellationPending                         获取一个值,指示应用程序是否已请求取消后台操作。通过在DoWork事件中判断CancellationPending属性可以认定是否需要取消后台操作(也就是结束线程);
        2、IsBusy                                                    获取一个值,指示 BackgroundWorker 是否正在运行异步操作。程序中使用IsBusy属性用来确定后台操作是否正在使用中;
        3、WorkerReportsProgress                     获取或设置一个值,该值指示BackgroundWorker能否报告进度更新
        4、WorkerSupportsCancellation            获取或设置一个值,该值指示 BackgroundWorker 是否支持异步取消。设置WorkerSupportsCancellati on为true使得程序可以调用CancelAsync方法提交终止挂起的后台操作的请求;
        重要方法:
        1、CancelAsync                 请求取消挂起的后台操作
        2、RunWorkerAsync            开始执行后台操作
        3、ReportProgress            引发ProgressChanged事件   
        重要事件:
        1、DoWork                            调用 RunWorkerAsync 时发生
        2、ProgressChanged         调用 ReportProgress 时发生
        3、RunWorkerCompleted    当后台操作已完成、被取消或引发异常时发生
        另外还有三个重要的参数是RunWorkerCompletedEventArgs以及DoWorkEventArgs、ProgressChangedEventArgs
        BackgroundWorker的各属性、方法、事件的调用机制和顺序:

从上图可见在整个生活周期内发生了3次重要的参数传递过程:
    参数传递1:此次的参数传递是将RunWorkerAsync(Object)中的Object传递到DoWork事件的DoWorkEventArgs.Argument,由于在这里只有一个参数可以传递,所以在实际应用往封装一个类,将整个实例化的类作为RunWorkerAsync的Object传递到DoWorkEventArgs.Argument;
    参数传递2:此次是将程序运行进度传递给ProgressChanged事件,实际使用中往往使用给方法和事件更新进度条或者日志信息;
    参数传递3:在DoWork事件结束之前,将后台线程产生的结果数据赋给DoWorkEventArgs.Result一边在RunWorkerCompleted事件中调用RunWorkerCompletedEventArgs.Result属性取得后台线程产生的结果。
    另外从上图可以看到DoWork事件是在后台线程中运行的,所以在该事件中不能够操作用户界面的内容,如果需要更新用户界面,可以使用ProgressChanged事件及RunWorkCompleted事件来实现。


在WinForm中经常遇到一些费时的操作界面,比如统计某个磁盘分区的文件夹或者文件数目,如果分区很大或者文件过多的话,处理不好就会造成“假死”的情况,或者报“线程间操作无效”的异常,为了解决这个问题,可以使用委托来处理,在.net2.0中还可以用BackgroundWorker类。

BackgroundWorker类是.net 2.0里新增加的一个类,对于需要长时间操作而不需要用户长时间等待的情况可以使用这个类。
注意确保在 DoWork 事件处理程序中不操作任何用户界面对象。而应该通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;


namespace BackgroundWorkerDemo
{
    public partial class MainForm : Form
    {
        private BackgroundWorker worker = new BackgroundWorker();
        public MainForm()
        {
            InitializeComponent();
            worker.WorkerReportsProgress = true;
            worker.WorkerSupportsCancellation = true;
            //正式做事情的地方
            worker.DoWork+=new DoWorkEventHandler(DoWork);
            //任务完称时要做的,比如提示等等
            worker.ProgressChanged += new ProgressChangedEventHandler(ProgessChanged);
            //任务进行时,报告进度
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(CompleteWork);
        }

        //调用 RunWorkerAsync 时发生
        public void DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = ComputeFibonacci(worker, e);//当ComputeFibonacci(worker, e)返回时,异步过程结束
        }
        //调用 ReportProgress 时发生
        public void ProgessChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;
        }
        //当后台操作已完成、被取消或引发异常时发生
        public void CompleteWork(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("完成!");
        }

        private int ComputeFibonacci(object sender, DoWorkEventArgs e)
        {
            for (int i = 0; i < 1000; i++)
            {
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                }
                else
                {
                    worker.ReportProgress(i);
                }
                System.Threading.Thread.Sleep(10);
            }
            return -1;
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            worker.RunWorkerAsync();
            btnStart.Enabled = false;
            btnPause.Enabled = true;
        }

        private void btnPause_Click(object sender, EventArgs e)
        {
            btnPause.Enabled = false;
            btnStart.Enabled = true;
            worker.CancelAsync();
        }
    }
}




本文转自黄聪博客园博客,原文链接http://www.cnblogs.com/huangcong/archive/2010/03/26/1697051.html,如需转载请自行联系原作者

相关文章
|
6月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
196 3
|
3月前
|
数据采集 XML JavaScript
C# 中 ScrapySharp 的多线程下载策略
C# 中 ScrapySharp 的多线程下载策略
|
2月前
|
安全 数据库连接 API
C#一分钟浅谈:多线程编程入门
在现代软件开发中,多线程编程对于提升程序响应性和执行效率至关重要。本文从基础概念入手,详细探讨了C#中的多线程技术,包括线程创建、管理及常见问题的解决策略,如线程安全、死锁和资源泄露等,并通过具体示例帮助读者理解和应用这些技巧,适合初学者快速掌握C#多线程编程。
76 0
|
4月前
|
SQL 开发框架 前端开发
在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
在C#开发中使用第三方组件LambdaParser、DynamicExpresso、Z.Expressions,实现动态解析/求值字符串表达式
|
3月前
|
安全 C# 开发者
【C# 多线程编程陷阱揭秘】:小心!那些让你的程序瞬间崩溃的多线程数据同步异常问题,看完这篇你就能轻松应对!
【8月更文挑战第18天】多线程编程对现代软件开发至关重要,特别是在追求高性能和响应性方面。然而,它也带来了数据同步异常等挑战。本文通过一个简单的计数器示例展示了当多个线程无序地访问共享资源时可能出现的问题,并介绍了如何使用 `lock` 语句来确保线程安全。此外,还提到了其他同步工具如 `Monitor` 和 `Semaphore`,帮助开发者实现更高效的数据同步策略,以达到既保证数据一致性又维持良好性能的目标。
43 0
|
5月前
|
并行计算 算法 C#
C# Mandelbrot和Julia分形图像生成程序更新到2010-9-14版 支持多线程计算 多核处理器
此文档是一个关于分形图像生成器的介绍,作者分享了个人开发的M-J算法集成及色彩创新,包括源代码和历史版本。作者欢迎有兴趣的读者留言交流,并提供了邮箱(delacroix_xu@sina.com)以分享资源。文中还展示了程序的发展历程,如增加了真彩色效果、圈选放大、历史记录等功能,并分享了几幅精美的分形图像。此外,还提到了程序的新特性,如导入ini文件批量输出图像和更新一批图片的功能。文档末尾附有多张程序生成的高分辨率分形图像示例。
|
5月前
|
大数据 C#
C#实现多线程的几种方式
C#实现多线程的几种方式
|
6月前
|
安全 Java 程序员
Java 多线程系列Ⅵ(并发编程的六大组件)
Java 多线程系列Ⅵ(并发编程的六大组件)
|
6月前
|
安全 Java C#
C#多线程详解
C#多线程详解
55 0