这是一个老问题了,对新手比较困惑,不过网上有很多讨论。.net 2.0之后,Winform控件默认不允许由非它所在的线程改变它的状态。如果你在其他的线程中改变控件的状态,则会抛出异常 Cross-thread operation not valid.窃以为,Control类对于多线程操作应该封装起来,不知道微软为何没这么做。这个问题解决也不难,Control有一个Invoke方法,它接受一个委托作为参数,它可以把委托中的代码加载到控件所在的线程中执行。Control类有个RequireInvoke属性,用来判断当前对控件的操作是否必须通过Invoke来执行,也就是,当前的代码是否和控件在同一个线程中。因此解决方案如下,假如我们有一个Form,上面有一个TextBox控件,TextBoxInformation,我们为Form添加一个方法,通过调用这个方法,其它线程也可以向这个textbox添加数据:
public void LogMessage(string message) { if (textBoxInfomation.InvokeRequired) { MethodInvoker fn = delegate { LogMessage(message); }; this.Invoke(fn); } else textBoxInfomation.Text += message + "\r\n"; }
其中,MethodInovker,是一个委托,不接受任何参数,.net 2.0 开始包括这个委托的声明。 这个方法很简单,就是判断下是否需要Invoke,如果需要,则新建一个委托,将这个方法本身传递给当前控件的线程执行。这个解决方案简单而无聊,如果有大量跨线程的方法,这样写就比较麻烦了。不过也没有太好的方法,如果你用的是.net 3.0,则可以使用extension method 来化简下,具体讨论见: