使用线程池(7)
使用BackgroundWorker组件
简介
使用BackgroundWorker组件,将代码组织为一系列的事件及事件处理器。
以下是代码实践:
using System;
using System.ComponentModel;
using System.Threading;
namespace 使用BackgroundWorker组件
{
internal class Program
{
private static void Main()
{
var bw = new BackgroundWorker
{
WorkerReportsProgress = true,//启用进度报告功能
WorkerSupportsCancellation = true//启用异步操作取消功能
};
bw.DoWork += Worker_DoWork;
bw.ProgressChanged += Worker_ProgressChanged;
bw.RunWorkerCompleted += Worker_Completed;
bw.RunWorkerAsync();
Console.WriteLine("Press C to cancel work");
do
{
if (Console.ReadKey(true).KeyChar=='c')
{
bw.CancelAsync();//请求取消异步操作
}
} while (bw.IsBusy);
}
private static void Worker_DoWork(object sender, DoWorkEventArgs e)
{
Console.WriteLine("DoWork thread pool id: {0}; Is thread pool thread: {1}",
Thread.CurrentThread.ManagedThreadId,Thread.CurrentThread.IsThreadPoolThread);
var bw = (BackgroundWorker) sender;
for (var i = 0; i <=100; i++)
{
if (bw.CancellationPending)//判断是否有取消操作的请求
{
e.Cancel = true;//取消异步操作
return;
}
if (i%10==0)
{
bw.ReportProgress(i);//报告进度
}
Thread.Sleep(TimeSpan.FromSeconds(0.1));
}
e.Result = 42;
}
private static void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Console.WriteLine("{0}% completed. Progress thread pool thread id: {1}",e.ProgressPercentage,
Thread.CurrentThread.ManagedThreadId);
}
//异步操作完成或取消后触发的事件程序
private static void Worker_Completed(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine("Completed thread pool thread id: {0}",Thread.CurrentThread.ManagedThreadId);
if (e.Error != null)
{
Console.WriteLine("Exception {0} has occured.",e.Error.Message);
}
else if (e.Cancelled)
{
Console.WriteLine("Operation has been canceled.");
}
else
{
Console.WriteLine("The answer is: {0}",e.Result);
}
}
}
}
总结
- 事件的处理器运行在线程池中;
- 这种方式称为基于事件的异步模式(Event-based Asynchronous Pattern,简称EAP)。这是历史上第二种用来构造异步程序的方式,现在更推荐使用TPL。
备注:学习《Multithreading in C# 5.0 Cookbook》Eugene Agafonov著的总结,以备日后查询。