C#中BackgroundWorker作为.NETFramework封装好的线程类,上手简单,可根据需要为其实例的DoWork、ProgressChanged、RunWorkerCompleted指定相应的委托:分别为DoWorkEventHandler、ProgressChangedEventHandler、RunWorkerCompletedEventHandler,然后再调用该实例的RunWorkerAsync(object argument==null)方法即可在单独线程(意思是非调用线程的另外线程中执行)。
坑,在BackgroundWorker的DoWork方法中操作UI控件(或其他异常)不报错。
老生常谈的东西,在.net中不允许在非ui线程是直接操作ui对象,BackgroundWorker亦是如此,DoWork中去直接操作控件对象(如文本框内容),不会报错,但会不执行该方法后的代码直接跳到RunWorkerCompleted(若已定义)执行。
RunWorkerCompleted中去修改控件内容则不需要通过textBox1.Invoke()来委托执行。(此处是BackgroundWorker线程结束,RunWorkerCompletedEventHandler的回调函数在主线程执行的原因,因为耗时2s的操作会卡住主线程)
public partial class Form1 : Form
{
public static BackgroundWorker Worker;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
textBox1.Text = "InitSuccess";
Worker = new BackgroundWorker();
Worker.DoWork += new DoWorkEventHandler(DoWork);
Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(WorkerCompleted);
}
private void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Thread.Sleep(2000);
textBox1.Text = "WorkerCompleted";
}
private delegate void EnableButtonCallBack();
private void DoWork(object sender, DoWorkEventArgs e)
{
ChangeText();//不会改变控件内容
//textBox1.Invoke(new EnableButtonCallBack(ChangeText));//可以改变控件内容
Thread.Sleep(1000);
}
private void ChangeText()
{
textBox1.Text = "DoWork";
}
private void button1_Click(object sender, EventArgs e)
{
Worker.RunWorkerAsync();
}
}