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