wusir 线程间操作无效: 从不是创建控件“”的线程访问它 解决办法_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > wusir 线程间操作无效: 从不是创建控件“”的线程访问它 解决办法

wusir 线程间操作无效: 从不是创建控件“”的线程访问它 解决办法

 2013/7/17 17:14:34  wusir  博客园  我要评论(0)
  • 摘要:利用FileSystemWatcher设计一个文件监控系统时,如果一个文件被修改或者新建,则文件修改事件会被多次触发而产生多条信息。为了将一个文件被修改一次而产生的多条信息归结为一条,在设计中新开了一个线程,在指定时间内(如2秒内)这个文件的修改被认为是一次修改,从而只产生一条信息。这个工作完成后,又出现了另外一个问题:因为需要在文件修改时,在Listbox控件中新增一条提示信息,代码是这样的:this.lstResults.Items.Add(info);结果在运行时出现了:线程间操作无效
  • 标签:解决办法 创建 解决 操作 控件 线程

利用FileSystemWatcher设计一个文件监控系统时,如果一个文件被修改或者新建,则文件修改事件会被多次触发而产生多条信息。为了将一个文件被修改一次而产生的多条信息归结为一条,在设计中新开了一个线程,在指定时间内(如2秒内)这个文件的修改被认为是一次修改,从而只产生一条信息。

这个工作完成后,又出现了另外一个问题:因为需要在文件修改时,在Listbox控件中新增一条提示信息,代码是这样的:

this.lstResults.Items.Add(info);

结果在运行时出现了:线程间操作无效: 从不是创建控件“lstResults”的线程访问它 这样的错误信息。根据VS2012上的帮助提示,直接进入到MSDN的帮助链接 http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k(EHInvalidOperation.WinForms.IllegalCrossThreadCall);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv2.0);k(DevLang-csharp)&rd=true

这里提出了线程安全的概念。就本错误信息而言,就是说,如果对一个控件的状态进行改变(比如设置其中的属性值),那么必须使用创建控件的线程来操作,如果不是创建控件的线程,那么,需要使用代理完成任务。MSDN具体的描述如下:

1、查询控件的InvokeRequired属性

2、如果InvokeRequired为true, 使用Invoke调用由委托封装的该控件操作

3、如果InvokeRequired为false, 直接对该控件进行操作

因此,要解决这个问题,需要

1、定义委托;

2、定义对应委托的方法,这个方法要完成该控件的操作;

3、将原来控件的操作,转换为调用委托方法的调用;

具体的解决办法如下:

        //define a delegate
        private delegate void testDelegate(string str);
        
        //define a method which match the above delegae
        private void testMethod(string str)
        {
            // query the control's(here is lstResults) InvokeRequired
            if (this.lstResults.InvokeRequired)
            {
                //instansiate a delegate with the method
                testDelegate myDelegate = new testDelegate(testMethod);
                //Invoke delegate
                this.lstResults.Invoke(myDelegate,str);
            }
            else
            {
                //InvokedRequired is false, so call the control directly
                this.lstResults.Items.Add(str);
            }
        }

 

 

原来的控件操作代码:

this.lstResults.Items.Add(info);

    改成了线程安全代码如下:

           //this.lstResults.Items.Add(info);
            //a thread-safe call
            this.testMethod(info);

      注意原来的控件操作代码被注释,实际操作放在testMethod()方法内。

上述办法是MSDN推荐的办法。

 

还有一种最简单的办法是改变属性:

Control.CheckForIllegalCrossThreadCalls = false; 

    这种办法直接屏蔽了错误信息的出现,一般情况下可以使用,但注意这个已经不是线程安全的办法了,它只是简单屏蔽了错误信息。

 

发表评论
用户名: 匿名