C#多线程 BackgroundWorker类使用小例

1. 示例程序 是一个控制台应用程序,程序实现了分别在主线程和后台线程并行执行,达到为数组赋值的效果。

可以中途停止后台线程。

2. 执行结果图片如下:

正常执行结束:

中途停止后台线程:

3.代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Threading;

namespace BackgroundWorker多线程
{
    class DoBackgroundwork
    {
        BackgroundWorker bgWorker = new BackgroundWorker();
        public int[] backArray{get;private set;}
        public bool CompletedNormally { get; private set; }

        //构造方法
        public DoBackgroundwork(int[] array)
        {
            this.backArray = array;

            bgWorker.WorkerReportsProgress = true;
            bgWorker.WorkerSupportsCancellation = true;

            bgWorker.DoWork += DoWork_Handler;
            bgWorker.ProgressChanged += ProgressChanged_Handler;
            bgWorker.RunWorkerCompleted += RunWorkerCompleted_Handler;
        }

        public void StartWorker()
        {
            if (!bgWorker.IsBusy)
            {
                bgWorker.RunWorkerAsync();
            }
        }

        public static int[] CalculateTheSequence(int[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                array[i] = 10 * i;
            }
            return array;
        }

        public void DoWork_Handler(object sender, DoWorkEventArgs args)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            //进行后台计算
            for (int i = 0; i < 10; i++)
            {
                //每一次迭代都检查是否已经取消
                if (worker.CancellationPending)
                {
                    args.Cancel = true;
                    worker.ReportProgress(-1);
                    break;
                }
                else
                {
                    //如果没有被取消则继续计算
                    CalculateTheSequence(backArray);
                    worker.ReportProgress((i+1)*10);

                    //让程序慢点,这样可以输出得漂亮一点
                    Thread.Sleep(100);
                }
            }
        }

        //处理后台线程的输入
        private void ProgressChanged_Handler(object sender,ProgressChangedEventArgs args)
        {
            string output = args.ProgressPercentage == -1 ? "            Cancelled" : string.Format("            back: {0}%        ", args.ProgressPercentage);
            Console.WriteLine(output);
        }

        //后台线程完成之后,总结并保存总和
        private void RunWorkerCompleted_Handler(object sender,RunWorkerCompletedEventArgs args)
        {
            CompletedNormally = !args.Cancelled;
        }

        public void Cancel()
        {
            if(bgWorker.IsBusy)
            {
                bgWorker.CancelAsync();
            }
        }

    }

    class Program
    {
        static void Main()
        {
            GiveInstructionsToTheUser();
            OutputTheSummaryHeaders();

            //创建并启动后台线程
            int[] backArray=new int[10];
            DoBackgroundwork bgw = new DoBackgroundwork(backArray);
            bgw.StartWorker();

            //主线程启动计算,对每一次循环,检查用户是否已经取消了后台线程
            //计算之后,进行短暂的休眠,这样程序可以慢一点,使得主线程不会比后台线程更快

            int[] mainArray = new int[10];
            for (int i = 0; i < 10; i++)
            {
                if (Program.CheckForCancelInput())
                    bgw.Cancel();

                CalculateTheSequenceMain(mainArray);
                Thread.Sleep(100);
                Console.WriteLine("main: {0}%", (i + 1) * 10);
            }
            SummarizeResults(bgw, mainArray);
            Console.ReadLine();
        }

        public static void GiveInstructionsToTheUser()
        {
            Console.WriteLine("本程序分别在主线程和后台线程并行计算两个数组的值。\n");
            Console.WriteLine("第一次按下 <Enter> 键开始执行主线程main和后台线程back.");
            Console.WriteLine("第二次按下 <Enter> 键停止执行后台线程back.");
            Console.ReadLine();
        }

        public static void OutputTheSummaryHeaders()
        {
            Console.WriteLine("------------------------");
        }

        private static void SummarizeResults(DoBackgroundwork bgw, int[] mainArray)
        {
            Console.WriteLine("\n\n运行结果:");
            Console.WriteLine("Main completed!");
            for (int i = 0; i < mainArray.Length;i++ )
            {
                Console.WriteLine("mainArray[" + i + "]:  " + mainArray[i]);
            }
            if (bgw.CompletedNormally)
            {

                Console.WriteLine("\nBackground completed!");
                for (int i = 0; i < bgw.backArray.Length; i++)
                {
                    Console.WriteLine("backArray[" + i + "]:  " + bgw.backArray[i]);
                }
            }
            else
            {
                Console.WriteLine("\nBackground Cancelled。");
            }

        }

        public static bool CheckForCancelInput()
        {
            bool doCancel = Console.KeyAvailable;
            if (doCancel)
                Console.ReadKey();
            return doCancel;
        }

        public static int[] CalculateTheSequenceMain(int[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                array[i] = i * i;
            }
            return array;
        }
    }
}
时间: 2024-11-10 15:18:12

C#多线程 BackgroundWorker类使用小例的相关文章

C#多线程 BackgroundWorker类使用小例-WPF程序

1.程序实现了一个简单的使用了BackgroundWorker类的WPF程序,用于在后台线程给进度条赋值. 运行结果如下: 后台线程正常运行结束: 后台线程中途被取消: 2.程序仅修改了 MainWindow.xaml 文件和 MainWindow.xaml.cs 文件,两个文件内容如下 MainWindow.xaml 文件: <Window x:Class="SimpleWorker.MainWindow" xmlns="http://schemas.microsof

C#多线程 定时重复调用异步线程即System.Threading.Timer类使用小例

1.System.Threading.Timer计时器提供了一种重复调用异步线程的方法..Net BCL中有多个Timer类,如用于Windows应用程序的System.Windows.Forms.Timer类,如可以运行在用户接口线程或工作线程上的System.Timers.Timer类.它们是很不一样的,这里要讲的System.Threading.Timer类是一种定时调用某个异步线程的类.每次计时器到设定的时间,系统就去线程池中开启一个线程运行提供的回调方法. 2.调用这个Timer类的重

thread学习笔记--BackgroundWorker 类

背景: 在 WinForms 中,有时要执行耗时的操作,比如统计某个磁盘分区的文件夹或者文件数目,如果分区很大或者文件过多的话,处理不好就会造成“假死”的情况,或者报“线程间操作无效”的异常,或者在该操作未完成之前操作用户界面,会导致用户界面停止响应. ----比如现在学习的MES UI中要查询数据量较大的记录显示在Spread中就可以用BackgroundWorker 类! 解决的方法就是新开一个线程,把耗时的操作放到线程中执行,这样就可以在用户界面上进行其它操作. 如果不借助Thread编程

java多线程实现卖票小程序

1 package shb.java.demo; 2 /** 3 * 多线程测试卖票小程序. 4 * @Package:shb.java.demo 5 * @Description: 6 * @author shaobn 7 * @Date 2015-9-2下午7:49:53 8 */ 9 public class TestSyn { 10 public static void main(String[] args) { 11 //此注释为实现方式一 12 /*TicketDemo td = n

深入剖析BackgroundWorker类

BackgroundWorker是一个在System.ComponentModel命名空间下的帮助类,用于管理工作线程.它提供了以下几个重要的特性: 1)“cancel”标记,可以在不使用Abort的情况下给工作线程打信号终止工作线程(调用CancelAsync方法). 2)提供报告进度.完成度和退出的标准方案 3)实现了IComponet接口,允许它参与Visual Studio设计器:可以直接从工具箱中拖出而不必写代码进行实例化 4)在工作线程上做异常处理 5)更新Windows Forms

新版API WordCount 小例 及如何导入jar包

WordCount: 简单解析wordcount小例子的代码,对应于新版的API进行处理. import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.examples.WordCount.TokenizerMapper; import org.apache.hadoop.fs.Path; im

dwr框架异步调用简单小例

DWR(Direct Web Remoting)是一个用于改善web页面与Java类交互的远程服务器端Ajax开源框架.可以轻松实现用js直接调用java方法. 通过一个小例子来演示一个dwr的基本使用: ①. 首先肯定要创建一个web project的,然后拷贝dwr.jar到WEB-INF\lib目录下 ②. 修改web.xml文件,添加dwr servlet配置 <servlet> <servlet-name>dwr-invoker</servlet-name>

2.匿名类,匿名类对象,private/protected/public关键字、abstract抽象类,抽象方法、final关键字的使用,多线程Thread类start方法原理

package com.bawei.multithread; //注意:模板方法我们通常使用抽象类或者抽象方法!这里我们为了方便在本类中使用就没有使用抽象类/抽象方法 public class TemplateThread { //如果这个方法不想被子类或者别人随意改动[这样子类就不能覆写该方法了],这里方法就要设置为final方法 public final void println(String message){ System.out.println("###################

Java多线程——ThreadLocal类

一.概述 ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是threadlocalvariable(线程局部变量).也许把它命名为ThreadLocalVar更加合适.线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突. 从线程的角度看,每个线程都保持一个对其线程局