Control的Invoke和BeginInvoke
参考资料:http://www.cnblogs.com/worldreason/archive/2008/06/09/1216127.html
http://www.cnblogs.com/c2303191/articles/826571.html
在多线程操作WinForm窗体上的控件时,需要使用Control的Invoke方法或BeginInvoke方法。Control的Invoke方法和BeginInvoke方法传递一个委托对象作为参数,它们的作用都是将它们的委托对象(也可以说是该委托对象的方法)交给UI线程去处理。为什么?因为另一个线程操作窗体上的控件时,会和UI线程(即主线程)产生竞争,造成不可预料的结果,甚至死锁。所以windows GUI编程有一个规则,就是只能通过创建控件的线程来操作控件的数据,否则就可能产生不可预料的结果。通俗点的说就是对控件的操作,只能在创建这个控件的线程中执行,否则无效!你是否记得在多线程上改变窗体上的控件时,出现的“线程间操作无效:从不是创建控件的XXX的线程访问它”报错提示?讲的就是这个原因。
那么Invoke和BeginInvoke又有什么差别?—对于调用Invoke的线程,在Invoke的方法返回前,这个线程会阻塞;对于调用BeginInvoke的线程,在BeginInvoke的方法返回前,这个线程不会阻塞!
// 声明委托类型 delegate void ShowMsgInTextBoxDelegate(string msg); // 创建委托对象,用于安全地将服务端发送过来的消息显示到文本框中 ShowMsgInTextBoxDelegate showMsgInTextBox = new ShowMsgInTextBoxDelegate(ShowMsgByDelegate); // 通过委托安全地将消息显示到文本框中 void ShowMsgByDelegate(string msg) { if (showMsgInTextBox != null) {
// this是Form窗体对象 if (this.InvokeRequired) // 判断调用Invoke的线程是否和控件是属于同一线程(判断是否跨线程访问控件) { this.Invoke(showMsgInTextBox, msg); // 或this.BeginInvoke(showMsgInTextBox, msg); } else { txtMsg.AppendText(msg + "\r\n"); } } }
具体更加详细的示例可以看看:http://www.cnblogs.com/c2303191/articles/826571.html。我就不再过多描述了!