zoukankan      html  css  js  c++  java
  • 线程间操作无效: 从不是创建控件的线程访问它.

    有两种方式解决 
    1.在窗体构造函数中写Control.CheckForIllegalCrossThreadCalls =false;
    2.使用Invoke等委托函数。
     
    问题原因是。net2.0以后拒绝多线程访问空间,避免空间造成死锁。以前Control.CheckForIllegalCrossThreadCalls =false;默认就是这样,现在默认为true。
    如果不会好几个线程同时操作一个控件用方法1就可以。如果存在多个线程一起操作控件使用方法2
     
    方法2可以
    
                        Invoke(new MethodInvoker(delegate()
                        {
                             //do something...                    }));
    我们在用线程操作的时候,可能会出现异常:线程间操作无效: 从不是创建控件richTextBox1的线程访问它。因为windows窗体控件不是线程安全的,如果几个线程操作某一控件的状态,可能会使该控件的状态不一致,出现争用或死锁状态。这种情况有以下解决办法:
    
    1. 可以在load时将CheckForIllegalCrossThreadCalls 属性的值设置为 false 。这样进行非安全线程访问时,运行环境就不去检验它是否是线程安全的。但是不推荐这种方法。
    
    2. 利用委托机制实现线程安全。第二种方法就是微软建议采用的跨线程调用的一种通用方法,就是使用代理来实现,就是将你所要操作的代码放到一个代理中,然后将这个代理交给创建这个控件的线程来执行你的代码。
    
    [c-sharp] view plaincopy
    private delegate void richTextBoxCallBack();  
           //建立一个委托  
      
           public void server()  
           {  
               richTextBoxCallBack callback = delegate()//使用委托  
               {  
                   string ip = getIP();//得到ip地址  
                   try  
                   {  
                       //获取txt文件的端口号  
                       StreamReader smReader = new StreamReader(path, System.Text.Encoding.UTF8);//设置路径    
                       string line;  
                       while ((line = smReader.ReadLine()) != null)  
                       {  
                           //string[] arrStr = line.Split('|');     //分割符 “|”        
                           port = Int32.Parse(line.Trim().ToString());  
                           //  MessageBox.Show(port.ToString());  
                       }  
                       smReader.Close();  
                       smReader.Dispose();  
                       IPAddress ipAddress = IPAddress.Parse(ip);  
                       //创建服务器的套接字  
                       listener = new TcpListener(ipAddress, port);  
                       //开始监听服务器端口  
                       listener.Start(13);  
      
                       //打出提示的信息  
                       this.richTextBox1.AppendText("Socket服务器已经启动,正在监听IP" +  
                           ip + " 端口号:" + port + "/n");     //从不是创建它的线程访问它的错误???  
                       //启动一个新的线程,执行方法this.StartSocketListen,  
                       //以便在一个独立的进程中执行确认与客户端Socket连接的操作  
                       SocketServiceFlag = true;//服务开始  
                       Thread thread = new Thread(new ThreadStart(this.StartSocketListen));  
                       thread.Start();  
                       this.button1.Enabled = false;  
                       this.button2.Enabled = true;  
                   }  
                   catch (Exception ex)  
                   {  
                       MessageBox.Show("服务器启动错误!!" + ex.Message);  
                   }  
               };  
               richTextBox1.Invoke(callback);  
                  
           }  
    
    建立一个委托 private delegate void richTextBoxCallBack(); 
    
    然后使用委托 richTextBoxCallBack callback = delegate(){}; //使用委托, 声明一个委托类型的变量callback ,{}之间的代码还是原来的方法的代码,最后richTextBox1.Invoke(callback);完成对该控件委托调用
    线程间操作无效: 从不是创建控件“”的线程访问它。
    听说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);
    
    大概就是这样的,貌似有听说最好别用第一种方法,具体为啥我也不知道~
    反正我一直都用委托的,也不是很麻烦~
  • 相关阅读:
    浅谈常量
    运算符
    TTL与CMOS门电路
    16位CRC校验_Delphi
    DXP快捷键记录(红色为经常用到的)
    论EFMS模拟量部分采集电路的修改
    稳压二极管应用电路_转载
    TVS二极管
    TryEnterCriticalSection___Delphi
    很好用的一个翻译插件
  • 原文地址:https://www.cnblogs.com/wangjiyuan/p/csharp1.html
Copyright © 2011-2022 走看看