Error:线程间操作无效: 从不是创建控件**的线程访问它

时间:2022-07-26 18:22:23

Error:线程间操作无效: 从不是创建控件**的线程访问它  


 

        这个问题延续至文件夹拷贝的功能,因为可能遇到文件夹内容很大,需要给出详细信息的情况。
通过对Thread.Start()方法的运用,知道了类中定义代理的用途,可以与控件交互。查阅了一些资料,先对Thread.Start()方法进行一个描述:

        在C#中,线程入口是通过ThreadStart代理(delegate)来提供的,你可以把ThreadStart理解为一个函数指针,指向线程要执行的函数,当调用C# Thread.Start()方法后,线程就开始执行ThreadStart所代表或者说指向的函数。
    而在程序调用中遇到的如题所示的错误,分析原因如下:因为线程所调用的对象生命周期不存在此线程中,所调用的控件是另一个线程所创建的,所以,线程可以调用它所创建的控件,而不是其他控件所声明的。
    解决方法
(1)法一:VS2003兼容方法处理,如下:
           publicForm1()    
                {    
                    InitializeComponent();                                                                                                         Control.CheckForIllegalCrossThreadCalls=false; 
        }    
方法二:微软建议作法,使用委托来修改主线程控件的属性。

(2)1. 可以在load时将CheckForIllegalCrossThreadCalls 属性的值设置为 false 。这样进行非安全线程访问时,运行环境就不去检验它是否是线程安全的。
2. 利用委托机制实现线程安全。上面的代码可以更改如下:
建立一个委托:delegate void SetLabelCallBack();

原来:

  1. private void tc_thread_SelectedIndexChanged(object sender, EventArgs e)   
  2.         {   
  3.             if (tc_timer.SelectedTab.Equals(tab1))   
  4.                 tab1.text = "showing tab1......";   
  5.             else if (tc_timer.SelectedTab.Equals(tab2))   
  6.             {   
  7.                 try  
  8.                 {   
  9.                     Thread myThread = new Thread(new ThreadStart(SetLabel));   
  10.                     myThread.Start();   
  11.                 }   
  12.                 catch (Exception ex)   
  13.                 {   
  14.                     MessageBox.Show(ex.Message);   
  15.                 }   
  16.             }   
  17.         }   
  18.   
  19. private void SetLabel()   
  20.        {   
  21.             myLabel.text = "showing tab2......";   
  22.        } 
    修改后:
  23. private void tc_thread_SelectedIndexChanged(object sender, EventArgs e)   
  24.         {   
  25.             if (tc_timer.SelectedTab.Equals(tab1))   
  26.                 tab1.text = "showing tab1......";   
  27.             else if (tc_timer.SelectedTab.Equals(tab2))   
  28.             {   
  29.                 try  
  30.                 {   
  31.                     Thread myThread = new Thread(new ThreadStart(SetLabel));   
  32.                     myThread.Start();   
  33.                 }   
  34.                 catch (Exception ex)   
  35.                 {   
  36.                     MessageBox.Show(ex.Message);   
  37.                 }   
  38.             }   
  39.         }   
  40.   
  41. private void SetLabel()   
  42.        {   
  43.             if(tc_thread.InvokeRequired)   
  44.             {   
  45.                 SetLabelCallBack labDele = new SetLabelCallBack(SetLabel);   
  46.                 this.Invoke(labDele, new object[]{});   
  47.             }   
  48.             else  
  49.             {   
  50.                 myLabel.text = "showing tab2......";   
  51.             }   
  52.        }