C#多线程更新界面有多种方法:
1. 使用Application.DoEvents();
2. 使用委托delegate
3. 使用BackgroundWorker; 最偷懒的办法(Winform/Silverlight通用)
4. 设置Control.CheckForIllegalCrossThreadCalls为false,相当于不检测线程之间的冲突
5. Dispatcher.BeginInvoke--Silverlight的独门秘籍
6. 利用SynchronizationContext上下文 -- 最神秘的方法(Winform/Silverlight能用)
本文只介绍第二种方法
执行前界面:一个ListBox,一个Button
执行后界面:
代码:
/// <summary>
/// 定义委托
/// </summary>
/// <param name="s"></param>
private delegate void MyDelegate(string s);
public Form1()
{
InitializeComponent();
}
private void Form4_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
for (int i = 0; i < 10; i++)//创建10个可以传递参数的线程
{
Thread ts = new Thread(new ParameterizedThreadStart(DoWork));
ts.Start(i);//不带参数的类型这里就不作介绍了,因为网上太多了
}
}
/// <summary>
/// 定义线程入口方法,并传递参数,注意这里的参数必须是object类型,在内部根据需要自行作类型转换
/// </summary>
/// <param name="obj"></param>
private void DoWork(object obj)
{
object obj1 = new object();
lock (obj1)
{
string s = obj.ToString();//根据需要对参数进行类型转换
MyDelegate md = new MyDelegate(SetText);//创建委托实例
Thread.Sleep(1 * new Random().Next(1, 32000));//随机休眠1-3000毫秒,有利于看清UI的更新,如果设置为固定时间,你几乎感觉不到是实时更新
/*
Do Some Work
*/
this.BeginInvoke(md, s);//UI线程上异步调用委托
}
}
/// <summary>
/// UI线程中用于更新界面的方法,其签名与上面定义的委托MyDelegate相同
/// </summary>
/// <param name="s"></param>
private void SetText(string s)
{
string s1 = s + "." + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:mm.ffffff");
listBox1.Items.Add(s1);
label2.Text = s1;//如果10个线程你看不到逐个添加的效果,可能就是因为你的CPU处理速度比较快,请加大线程数量,这样可以看到滚动条在不断变窄,或者你也可以在此加上Label单条显示,这样更明显
}
}