C#中多线程修改UI
程序描述:
如图所示,点击”写入数据“按钮后,会启动一个线程,该线程往一个文件写10000数据,每写一行数据,同时更新主线程的UI
代码如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading; using System.Windows.Forms; namespace threadUI { public partial class Form1 : Form { delegate void AsyncUpdateUI(int step); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { int taskCount = 10000; //任务量为10000 this.pgbWrite.Maximum = taskCount; this.pgbWrite.Value = 0; DataWrite dataWrite = new DataWrite();//实例化一个写入数据的类 dataWrite.UpdateUIDelegate += UpdataUIStatus;//绑定更新任务状态的委托 dataWrite.TaskCallBack += Accomplish;//绑定完成任务要调用的委托 Thread thread = new Thread(new ParameterizedThreadStart(dataWrite.Write)); thread.IsBackground = true; thread.Start(taskCount); } private void UpdataUIStatus(int step) { if (InvokeRequired) { this.Invoke(new AsyncUpdateUI(delegate(int s) { this.pgbWrite.Value += s; this.lblWriteStatus.Text = this.pgbWrite.Value.ToString() + "/" + this.pgbWrite.Maximum.ToString(); }), step); } else { this.pgbWrite.Value += step; this.lblWriteStatus.Text = this.pgbWrite.Value.ToString() + "/" + this.pgbWrite.Maximum.ToString(); } } //完成任务时需要调用 private void Accomplish() { //还可以进行其他的一些完任务完成之后的逻辑处理 MessageBox.Show("任务完成"); } } public class DataWrite { public delegate void UpdateUI(int step);//声明一个更新主线程的委托 public UpdateUI UpdateUIDelegate; public delegate void AccomplishTask();//声明一个在完成任务时通知主线程的委托 public AccomplishTask TaskCallBack; public void Write(object lineCount) { System.IO.StreamWriter writeIO = new System.IO.StreamWriter("text.txt", false, Encoding.GetEncoding("gb2312")); for (int i = 0; i < (int)lineCount; i++) { writeIO.WriteLine(i.ToString() + ",dummy data"); //写入一条数据,调用更新主线程ui状态的委托 UpdateUIDelegate(1); } //任务完成时通知主线程作出相应的处理 TaskCallBack(); writeIO.Close(); } } }
关键代码:
private void UpdataUIStatus(int step) { if (InvokeRequired) { this.Invoke(new AsyncUpdateUI(delegate(int s) { this.pgbWrite.Value += s; this.lblWriteStatus.Text = this.pgbWrite.Value.ToString() + "/" + this.pgbWrite.Maximum.ToString(); }), step); } else { this.pgbWrite.Value += step; this.lblWriteStatus.Text = this.pgbWrite.Value.ToString() + "/" + this.pgbWrite.Maximum.ToString(); } }
InvokeRequired用于判断是否是控件所在线程调用的,如果不是的则为true。Invoke用于跨线程调用控件。
更多关于Invoke用法的例子,使用方法本身作为委托。
private void msg() { if (this.InvokeRequired) { this.Invoke(new MethodInvoker(msg)); } else { textBox2.Text += Environment.NewLine + " >> " + readData; MessageBox.Show("hi"); } }
这里MethodInvoker就是一个代理类型
public delegate void MethodInvoker();
总结Invoke的参数,
第一个是委托对象,后面是不定参数。可以写成new object[]{p1,p2...}
所以,本例程中this.Invoke的代码可以写出
this.Invoke(new AsyncUpdateUI(UpdataUIStatus),new object[]{step});
或者直接
this.Invoke(new AsyncUpdateUI(UpdataUIStatus),step);