导航

关于异常 “线程间操作无效: 从不是创建控件“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         }
WriteDescription

          其中lvShow.Invoke(ROPeration,new object[]{Index,Description}); 是使用控件调用委托,可以说是在创建控件的线程上完成操作。使用的时候,同样是直接调用WriteDescription( , ) 函数。这段代码给我的感觉稍微有些像递归。

          摘抄一句别人博客上写的理解“控件是主线程创建的,它依附于创建窗体的主线程.因此,要在子线程去访问占资源的类型,我们需要跨线程调用X.InvokeRequire用于判断是否需要跨线程,返回True为需要跨线程,此时你需要定义一个委托类来将一个含赋值语句的方法封装起来,通过X.Invoke来调用这个委托”。

          解决方法就是上面这样了。

          

posted on 2013-06-07 16:40  吉祥天  阅读(295)  评论(0)    收藏  举报