关于异常 “线程间操作无效: 从不是创建控件“X”的线程访问它”
关于这个异常,其实我已经遇到过几次了,但是真正解决确实在今天。从网上找到的一些资料,然后再实现后测试,发现这个方法确实能够解决问题,所以今天记录在这里。
这次遇到的问题是在实现:利用ListView控件显示文本信息的时候出现的。我在创建窗体的主线程开启了一个线程,来向控件写信息,直接调用的函数,偶尔会出现“线程间操作无效”的异常。
在网上查找后,发现有两条办法。贴出来如下:
1.在VS 2005 环境下,窗体属性赋值 System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
不过,各种评论表示这种办法,不够安全稳定。
2.使用安全委托,实现“写”的动作。我用的就是这种办法,不过使用的时候,和我平常用的事件委托还有一些不同,是直接由控件调用委托。
我把代码贴出来:
1 public delegate void lvOperation(int Index, string Description); 2 3 public void WriteDescription(int Index, string Description) 4 { 5 try 6 { 7 if (lvShow.InvokeRequired == true) 8 { 9 lvOperation ROperation = new lvOperation(WriteDescription); 10 lvShow.Invoke(ROperation, new object[] { Index,Description }); 11 } 12 else 13 { 14 lvShow.BeginUpdate(); 15 if (lvShow.Items.Count > 50) 16 { 17 lvShow.Items[0].Remove(); 18 } 19 20 lvShow.Items.Add(eventDescription, signIconIndex); 21 lvShow.Items[lvRunInfo.Items.Count - 1].EnsureVisible(); 22 lvShow.Items[lvRunInfo.Items.Count - 1].Selected = true; 23 lvShow.EndUpdate(); 24 } 25 } 26 catch (Exception ex) 27 { 28 29 } 30 }
其中lvShow.Invoke(ROPeration,new object[]{Index,Description}); 是使用控件调用委托,可以说是在创建控件的线程上完成操作。使用的时候,同样是直接调用WriteDescription( , ) 函数。这段代码给我的感觉稍微有些像递归。
摘抄一句别人博客上写的理解“控件是主线程创建的,它依附于创建窗体的主线程.因此,要在子线程去访问占资源的类型,我们需要跨线程调用X.InvokeRequire用于判断是否需要跨线程,返回True为需要跨线程,此时你需要定义一个委托类来将一个含赋值语句的方法封装起来,通过X.Invoke来调用这个委托”。
解决方法就是上面这样了。
浙公网安备 33010602011771号