• 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法~ 线程间操作无效: 从不是创建控件“Control Name'”的线程访问它问题的解决方案及原理分析


    看两个例子,一个是在一个进程里设置另外一个进程中控件的属性。另外一个是在一个进程里获取另外一个进程中控件的属性。

    第一个例子

    最近,在做一个使用线程控制下载文件的小程序(使用进度条控件显示下载进度)时,遇到这样的问题,

    错误显示:

    未处理的“System.InvalidOperationException”类型的异常出现在 System.Windows.Forms.dll 中。

    其他信息: 线程间操作无效: 从不是创建控件“progressBar1”的线程访问它。

    以前很少做关于线程的程序,而且对于线程的理解也不是很深,无奈只好百度之。很快从网上找到了解决方案:

    方法1、在Form Load事件中加入

     
    System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
    这是是最简单的方式!

    方法二、使用Invoke调用委托

    参考示例代码:


    1.定义 委托
       delegate void myDelegate(int i);
       myDelegate mydelegate = null;

    2.定义方法,显示消息

     public void ShowMessage(int i)
            {
                this.textBox1.Text = i.ToString();
                this.progressBar1.Value = i;
            }


    3.定义方法,驱动消息

     public void MyEvent()
            {
                for (int i = 0; i < 100; i++)
                {
                    Thread.Sleep(100);
                    this.BeginInvoke(mydelegate, new object[] {i});
                
                }
            }


    4: 运行
      private void button1_Click(object sender, EventArgs e)
            {
                mydelegate = new myDelegate(ShowMessage);
                Thread myThread = new Thread(MyEvent);

                //IsBackground 是否后台
                //这个属性很重要 .如果 Thread IsBackground 等于false
                // 当线程还没有结束时,你点了关闭按钮
                // 将抛出An unhandled exception
                //of type 'System.InvalidOperationException'
                //occurred in System.Windows.Forms.dll 异常
                myThread.IsBackground = true;
                myThread.Start();
            }

    问题分析:

    根据错误提示,可知在调试器中运行应用程序时,如果不是控件的创建者线程试图调用该控件时,则调试器会引发 InvalidOperationException,并提示消息:“从不是创建控件 Control Name 的线程访问它。” 说白了,就是资源访问的不一致性,控件的调用者线程不是控件的创建者线程,这是.net实现资源安全访问机制的必然结果。访问 Windows 窗体控件本质上不是线程安全的。如果多个线程同时操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。

    第二个例子

    线程间操作无效: 从不是创建控件“”的线程访问它。
    听说2003里边不会,我不知道是不是这样的,反正一直都在用05~
    05里会出这个问题的,貌似是为了安全~
    哦,现在知道的解决方法有两个~

    第一:

    Control.CheckForIllegalCrossThreadCalls = false;


    线程开始的时候加这么一句,OK,看不到错误了~
    啥都能用了~

    第二:
    用委托,在05里,每个控件都有个InvokeRequired的属性~
    判断一下是不是true,是的话进行Invoke操作的,完事了~

     

    //建立个委托
    private delegate string returnStrDelegate();

    //搞个最简单滴取值滴方法~
    private string returnSchool()
            {
                return CB_School.SelectedValue.ToString();
            }

    //判断一下是不是该用Invoke滴~,不是就直接返回~
    private string returnCB(returnStrDelegate myDelegate)
            {
                if (this.InvokeRequired)
                {
                    return (string)this.Invoke(myDelegate);
                }
                else
                {
                    return myDelegate();
                }
            }

    //别的线程里的调用哇~
    string _school = returnCB(returnSchool);


    大概就是这样的,貌似有听说最好别用第一种方法,具体为啥我也不知道~
    反正我一直都用委托的,也不是很麻烦~

    麻烦知道的更清楚的人给说一声为什么,谢谢了~

  • 相关阅读:
    线程的异常捕获与线程池的异常捕获
    设计模式-状态模式
    老王讲自制RPC框架.(四.序列化与反序列化)
    老王讲自制RPC框架.(三.ZOOKEEPER)
    老王讲自制RPC框架.(二.动态代理)
    4
    3
    2
    1
    前言
  • 原文地址:https://www.cnblogs.com/yuxuetaoxp/p/3873074.html
Copyright © 2020-2023  润新知