BackGroundWorker实际上是一个异步的事件进度控制控件,通常结合进度条ProgressBar一起使用,如下测试源码
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace BackGroundWorker
{
public partial class BgWorkerForm : System.Windows.Forms.Form
{
public BgWorkerForm()
{
InitializeComponent();
//指示BackgroundWorker是否可以报告进度更新。为True时,将可以成功调用ReportProgress方法,否则将引发InvalidOperationException异常。
bgWorker.WorkerReportsProgress = true;
//指示BackgroundWorker是否支持异步取消操作。为True时,将可以成功调用CancelAsync方法,否则将引发InvalidOperationException异常。
bgWorker.WorkerSupportsCancellation = true;
bgWorker.DoWork += BgWorker_DoWork; //执行异步操作的函数,在另一个线程中执行
bgWorker.ProgressChanged += BgWorker_ProgressChanged; //报告进度更新的函数
bgWorker.RunWorkerCompleted += BgWorker_RunWorkerCompleted; //报告进度完成的函数
string uiID = Thread.CurrentThread.ManagedThreadId.ToString(); //或AppDomain.GetCurrentThreadId().ToString()
mainUiLabel.Text = string.Format("主UI线程ID为:{0}", uiID);
}
private void BgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.ToString());
return;
}
if (!e.Cancelled) //判断是否人为终止
infoLabel.Text = "处理完毕!";
else
infoLabel.Text = "处理终止!";
string RunWorkerCompletedID = Thread.CurrentThread.ManagedThreadId.ToString(); //或AppDomain.GetCurrentThreadId().ToString()
runWorkerCompletedLabel.Text = string.Format("RunWorkerCompleted运行线程ID为:{0}", RunWorkerCompletedID);
doWorkLabel.Text = string.Format("DoWork运行线程ID为:{0}", DoWorkID);
}
private void BgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage; //获取报告值
// Extract the argument.
string param = (string)e.UserState; //Working...
infoLabel.Text = "处理进度:" + Convert.ToString(e.ProgressPercentage) + "%";
string ProgressChangedID = Thread.CurrentThread.ManagedThreadId.ToString(); //或AppDomain.GetCurrentThreadId().ToString()
progressChangedLabel.Text = string.Format("ProgressChanged运行线程ID为:{0}", ProgressChangedID);
}
private string DoWorkID;
private void BgWorker_DoWork(object sender, DoWorkEventArgs e)
{
// Do not access the form's BackgroundWorker reference directly.
// Instead, use the reference provided by the sender parameter.
BackgroundWorker bw = sender as BackgroundWorker;
// Extract the argument.
string param = (string)e.Argument; //param
// If the operation was canceled by the user,
// set the DoWorkEventArgs.Cancel property to true.
//在DoWork中键入如下代码
for (int i = 0; i <= 100; i++)
{
if (bw.CancellationPending) //状态,可检索是否取消了
{
//Cancel事件发生后仍会先进这里,这个函数完结了才会调用BgWorker_RunWorkerCompleted
//这里的标志位决定了后续BgWorker_RunWorkerCompleted里的标志位
e.Cancel = true;
return;
}
else
{
bw.ReportProgress(i, "Working..."); //提交状态报告,将触发BgWorker_ProgressChanged事件
System.Threading.Thread.Sleep(100);
}
}
DoWorkID = Thread.CurrentThread.ManagedThreadId.ToString(); //或AppDomain.GetCurrentThreadId().ToString()
}
private void startBtn_Click(object sender, EventArgs e)
{
if (bgWorker.IsBusy)return; //避免还处在工作状态时被重复触发
progressBar.Maximum = 100;
bgWorker.RunWorkerAsync("param");
}
private void cancelBtn_Click(object sender, EventArgs e)
{
bgWorker.CancelAsync(); //停止运行
}
private void Form_Load(object sender, EventArgs e)
{
}
}
}
运行效果:
我们发现仅DoWork事件运行在另一条线程,其他事件均在主UI线程运行。