在多线程中处理界面的响应信息,确实没有单线程那么容易,直接赋值就OK了,必须得通过委托到主线程中才可以处理,这个小DEMO实现了两个线程同时在主界面上进行输入.当初自己怎么也弄不明白这些道理,只要弄出第一个实例,后面的就轻松多了,万事入门难嘛.直接贴代码,解释都在注释里了,其他就不多废话了.
- private void button1_Click(object sender, EventArgs e)
- {
- //初学的时候这里经常弄不清楚到底是该用ThreadStart还是用Thread
- //其实没有必要一定要弄到ThreadStart的,它只是使用委托线程
- //Thread t = new Thread (new ThreadStart (Go));相当于下面的写法:
- //public delegate void ThreadStart();
- //Thread t = new Thread (new ThreadStart (Go));编译的时候将和委托一样
- //Thread t = new Thread (delegate() { Go中的代码 });
- Thread s1 = new Thread(addwebper1s);
- //IsBackground是申明一个后台线程,为什么做后台线程呢?
- //因为主线程退出的时候,后台线程会自动销毁,否则回驻留在内存中
- s1.IsBackground = true;
- s1.Start();
- Thread s2 = new Thread(addwebper2s);
- s2.IsBackground = true;
- s2.Start();
- }
- private void addwebper2s()
- {
- while (true)
- {
- AddMsg("http://www.csdn.net/r/n");
- //线程休眠2秒
- Thread.Sleep(2 * 1000);
- }
- }
- private void addwebper1s()
- {
- while (true)
- {
- AddMsg("http://blog.csdn.net/much0726/r/n");
- //线程休眠1秒
- Thread.Sleep(1 * 1000);
- }
- }
- delegate void addmsg(string msg);
- private void AddMsg(string msg)
- {
- //把鼠标放上去看解释就知道了,就是防止创建控件以外的线程调用(.NET是类型安全的)
- if (this.InvokeRequired)
- {
- //为当前控件指定委托
- this.Invoke(new addmsg(AddMsg), msg);
- }
- else
- {
- //被委托到主线程后真正执行的代码
- //为什么会执行到这里?
- //不好解释,大概是因为委托的主线程后,this.InvokeRequired=false了吧
- textBox1.Text += msg;
- }
- }
小结
虽然在多线中访问主线中的控件资源,表象看来,好象必须要对改控件进行互斥锁,但是,实际上是没有必要的,这点我也没有弄明白为什么,在多线程中,复杂的界面响应也会给程序带来更多的BUG,测试成本会无形的扩大,个人建议,如果是服务端程序就使用控制太的Console输出就可以了,如果是用户体验要求比较高的程序,需要进行多方面的压力测试才行.