![]() |
【转帖】WinForm/Silverlight多线程编程中如何更新UI控件的值
http://www.cnblogs.com/yjmyzz/archi...25/1610253.html
单线程的winfom程序中,设置一个控件的值是很easy的事情,直接 this.TextBox1.value = "Hello World!";就搞定了,但是如果在一个新线程中这么做,比如: privatevoid btnSet_Click(object sender, EventArgs e) { Thread t =new Thread(new ParameterizedThreadStart(SetTextBoxValue)); //当然也可以用匿名委托写成Thread t = new Thread(SetTextBoxValue); t.Start("Hello World"); } void SetTextBoxValue(object obj) { this.textBox1.Text = obj.ToString(); } 运行时,会报出一个无情的错误: 线程间操作无效: 从不是创建控件“textBox1”的线程访问它。 究其原因,winform中的UI控件不是线程安全的,如果可以随意在任何线程中改变其值,你创建一个线程,我创建一个线程,大家都来抢着更改"TextBox1"的值,没有任何秩序的话,天下大乱... 解决办法: 1.掩耳盗铃法(Control.CheckForIllegalCrossThreadCalls = false;)--仅Winform有效 using System; using System.Threading; using System.Windows.Forms; namespace ThreadTest { publicpartialclass Form1 : Form { public Form1() { InitializeComponent(); Control.CheckForIllegalCrossThreadCalls =false;//这一行是关键 } privatevoid btnSet_Click(object sender, EventArgs e) { Thread t =new Thread(new ParameterizedThreadStart(SetTextBoxValue)); t.Start("Hello World"); } void SetTextBoxValue(object obj) { this.textBox1.Text = obj.ToString(); } } } 设置Control.CheckForIllegalCrossThreadCalls为false,相当于不检测线程之间的冲突,允许各路线程随便乱搞,当然最终TextBox1的值到底是啥难以预料,只有天知道,不过这也是最省力的办法 2.利用委托调用--最常见的办法(仅WinForm有效) using System; using System.Threading; using System.Windows.Forms; namespace ThreadTest { publicpartialclass Form1 : Form { delegatevoid D(object obj); public Form1() { InitializeComponent(); } privatevoid btnSet_Click(object sender, EventArgs e) { Thread t =new Thread(new ParameterizedThreadStart(SetTextBoxValue)); t.Start("Hello World"); } void SetTextBoxValue(object obj) { if (textBox1.InvokeRequired) { D d =new D(DelegateSetValue); textBox1.Invoke(d,obj); } else { this.textBox1.Text = obj.ToString(); } } void DelegateSetValue(object obj) { this.textBox1.Text = obj.ToString(); } } } |
所有的时间均为北京时间。 现在的时间是 05:22 PM. |