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;
        }
    }
}

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。