转自:http://www.sunnychen.org/trackback.asp?tbID=124&action=addtb&tbKey=43c0d85c8d6d5dcc018d174276ac098da9245500
在.NET中如需在非UI线程中改变UI控件属性时,CLR会抛出异常,提示无法在非UI线程中更新界面上的控件(Cross-thread operation not valid)。一般情况下有两种解决办法。第一种就是设置Control的静态属性CheckForIllegalCrossThreadCalls为False,如下:
01public Form1() 02{ 03 InitializeComponent(); 04 Control.CheckForIllegalCrossThreadCalls = false; 05} 06 07private void button1_Click(object sender, EventArgs e) 08{ 09 Thread thread = new Thread(() => 10 { 11 for (int i = 0; i < 100000; i++) 12 { 13 label1.Text = i.ToString(); 14 label1.Refresh(); 15 } 16 }); 17 thread.Start(); 18}另一种办法,就是使用委托,根据控件的InvokeRequired属性判断当前控件的更新操作是否是在另一个线程中。如果是,则使用委托进行方法调用并更新控件。但是这种方法有个缺点,就是需要针对每个控件的属性设置方式创建一些单独的委托和方法,这些委托和方法仅仅是在解决跨线程操作的时候使用。比如,你在另一个线程中需要修改某个label的text时,你就需要创建一个SetLabelText方法,假设你还需要更新TextBox的text,那么你还需要另外创建一个SetTextBoxText方法。
通过下面的委托和方法的定义,我们实现了“一次定义,多次使用”。请看:
view source print ? 01private delegate void ParameterizedControlUpdate(params object[] args); 02 03private delegate void ControlUpdateDelegate(Component c, 04 ParameterizedControlUpdate callback, 05 params object[] args); 06 07private void DelegatedControlUpdate(Component c, 08 ParameterizedControlUpdate callback, 09 params object[] args) 10{ 11 Control target = (c is Control) ? (c as Control) : this; 12 if (target.InvokeRequired) 13 { 14 ControlUpdateDelegate d = DelegatedControlUpdate; 15 target.Invoke(d, new object[] { c, callback, args }); 16 } 17 else 18 { 19 callback(args); 20 } 21}于是,上面的例子可以改为:
view source print ? 01private void button1_Click(object sender, EventArgs e) 02{ 03 Thread thread = new Thread(() => 04 { 05 for (int i = 0; i < 100000; i++) 06 { 07 DelegatedControlUpdate(label1, args => 08 { 09 label1.Text = (string)args[0]; 10 label1.Refresh(); 11 }, i.ToString()); 12 } 13 }); 14 thread.Start(); 15}
转载于:https://www.cnblogs.com/antony1029/archive/2010/10/10/1847176.html
相关资源:qt编程_在子线程中更新UI界面