線程間操作無效: 從不是創建控件“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 窗體控件本質上不是線程安全的。如果多個線程同時操作某一控件的狀態,則可能會迫使該控件進入一種不一致的狀態。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章