码迷,mamicode.com
首页 > 编程语言 > 详细

线程间操作无效: 从不是创建控件“button1”的线程访问它。

时间:2015-04-17 23:46:06      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:

.net2后是不能跨线程访问控件的。,窗体上的控件是当前主线程创建的,当用户异步执行一个方法:在该方法中给窗体上的控件赋值,记住:当执行一个异步委托的时候,其实

就是开了一个线程去执行那个方法,这样就会报错:线程间操作无效: 从不是创建控件“某某某”的线程访问它。

 

C# WinForm开 发中,这是一个比较常见的异常:线程间操作无效,从不是创建控件“xxx”的线程访问它。这个异常来源于.NET2的一个限制:工作线程不能访问窗口线程 创建的控件。解决方法主要有两种,一种是在窗口线程中设置CheckForIllegalCrossThreadCalls = false ;另一种方式比较麻烦,使用委托的方式调用Invoke方法。

 public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

但以上不是推荐的方法。更好的办法是用委托解决

  private void button1_Click(object sender, EventArgs e)
        {
            new Action(show).BeginInvoke(null, null);
        }

        void show()
        {
            //异步外的方法。这样窗体不会假死
            while (true)
            {
                Thread.Sleep(2000);
                Action ac = new Action(showText);
                this.Invoke(ac); //在同步方法里面实现更新窗体上的数据
            }
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        void showText()
        {
            richTextBox1.AppendText("更新\n");
        }

或者使用InvokeRequired属性判断

 /*
             // 摘要:
        //     获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。
        //
        // 返回结果:
        //     如果控件的 System.Windows.Forms.Control.Handle 是在与调用线程不同的线程上创建的(说明您必须通过 Invoke
        //     方法对控件进行调用),则为 true;否则为 false。

private void button1_Click(object sender, EventArgs e)
        {
            //new Action(show).BeginInvoke(null, null);
            new Action(show1).BeginInvoke(null, null);
        }
        void show1()
        {
            while (true)
            {
                Thread.Sleep(2000);//模拟等待效果
                show2();
            }
        }

        void show2()
        {
            //说明的当前外部线程
            /*
             // 摘要:
        //     获取一个值,该值指示调用方在对控件进行方法调用时是否必须调用 Invoke 方法,因为调用方位于创建控件所在的线程以外的线程中。
        //
        // 返回结果:
        //     如果控件的 System.Windows.Forms.Control.Handle 是在与调用线程不同的线程上创建的(说明您必须通过 Invoke
        //     方法对控件进行调用),则为 true;否则为 false。
             */
            if (InvokeRequired)
            {
                /*既然是外部线程,那么就没有权限访问主线程上的控件
                 * 故要主线程访问,开启一个异步委托捆绑要执行的方法
                 * 交给主线程执行
                 */
                Action ac = new Action(show2);
                this.Invoke(ac); //这里执行后。则InvokeRequired就为false。因为此时已经是主线程访问当前创建的控件
            }
            else
            {
                richTextBox1.AppendText("更新77\n");
            }
        }

 

 

参考:http://www.cnblogs.com/txw1958/archive/2012/08/21/2649192.html

线程间操作无效: 从不是创建控件“button1”的线程访问它。

标签:

原文地址:http://www.cnblogs.com/nsky/p/4436309.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!