C#中的BackgroundWoker在GUI中用于替代多线程是一个比较理想的实现方式。下面记录使用BackgroundWorker的详细方法。
BackgroundWoker有三个事件分别为DoWork、ProgressChanged、RunWorkerCompleted分别用于出发后台处理事件、进度报告和处理事件完成。
DoWork的委托形式为 void (object sender,DoWorkEventArgs args)。该委托用于处理后台线程需要处理的事情。同时在该委托中好需要使用BackgroundWorker的CancellationPending属性检测用户时候取消了后台线程,如果用户取消后台线程则需要设置DoWorkEventArgs的Cancel属性为true,这样再RunWorkerCompleted事件中可以检测到后台线程是正常终止还是被用户终止的。
ProgressChanged的委托形式为void (object sender,ProgressChangedEventArgs args)。该委托用户向用户报告当前线程的进度。具体进度可以通过从PorgressChangedEventArgs参数中ProgressPercentage属性获取,该属性为一个1到100的Int。需注意的是,只有在DoWork委托中使用BackgroundWoker的ReportProgress()方法后才会出发ProgressChanged事件,该方法接受一个1到100的Int参数。
RunWorkerCompleted的委托形式为void (object sender,RunWorkerCompletedEventArgs args)。该委托用户在BackgroundWorker完成后调用(触发)。通过检查RunWorkerCompletedEventArgs参数的cancel属性可以检测是正常终止还是被用户终止。
BackgroundWorker类的常用方法有:RunWorkerAsync() 、CancelAsync()和 ReportProgress()。RunWokerAsync()方法用于开始后台线程。CancelAsync()方法用于终止线程,但是他实际上并没有终止线程,而是修改了BackgroundWorker的CancellationPending属性为ture,然后通过在DoWork事件中检测该属性来终止后台线程。ReportProgress用于触发ProgressChanged事件,如果在DoWork中没有调用ReportProgress()方法,则ProgressChanged事件不会发生。
BackgroundWorker类的常用属性有:CancellationPending、IsBusy 、WorkerReportsProgress WorkerSupportsCancellation。他们都是bool型。CancellationPending 用于表示是否终止当前后台线程。IsBusy用于表示当前后台线程时候运行。前面这两者都是只读型。WorkerReportsProgress表示是否支持进度报告。WorkerSupportsCancellation表示是否支持后台线程终端。
下面给一个例子说明:
using System;
using System.ComponentModel;
using System.Threading;
namespace Ch22
{
class WebData
{
private BackgroundWorker bgWorker;
public WebData()
{
bgWorker=new BackgroundWorker();
bgWorker.WorkerSupportsCancellation=true;
bgWorker.WorkerReportsProgress=true;
bgWorker.DoWork+=GetData;
bgWorker.RunWorkerCompleted+=Complete;
bgWorker.ProgressChanged+=ReportProgress;
}
public void Start()
{
if(bgWorker!=null)
{
bgWorker.RunWorkerAsync();
}
}
public void Cancel()
{
if(bgWorker.IsBusy)
{
try
{
bgWorker.CancelAsync();
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
private void GetData(object sender,DoWorkEventArgs args)
{
for(int i=0;i<100;i++)
{
if(bgWorker.CancellationPending)
{
args.Cancel=true;
break;
}
bgWorker.ReportProgress(i);
Thread.Sleep(1000);
}
}
private void Complete(object sender,RunWorkerCompletedEventArgs args)
{
if(args.Cancelled)
{
Console.WriteLine("BackgroundWorker has been Cancelled");
}
else
{
Console.WriteLine("BackgroundWoker has completed");
}
}
private void ReportProgress(object sender,ProgressChangedEventArgs args)
{
Console.SetCursorPosition(0,3);
Console.WriteLine("Geting Data...{0}%",args.ProgressPercentage);
}
}
class Program
{
public static void Main()
{
WebData bg=new WebData();
bg.Start();
while(true)
{
if(Console.KeyAvailable)
{
Console.ReadKey();
bg.Cancel();
}
}
}
}
}