1. 程式人生 > >跨執行緒呼叫DataGridView控制元件

跨執行緒呼叫DataGridView控制元件

訪問 Windows 窗體控制元件本質上不是執行緒安全的。如果有兩個或多個執行緒操作某一控制元件的狀態,則可能會迫使該控制元件進入一種不一致的狀態。還可能出現其他與執行緒相關的 bug,包括爭用情況和死鎖。確保以執行緒安全方式訪問控制元件非常重要。 

雖然可以使用如下:

System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;

來禁止檢查控制元件是否被非建立自己的執行緒操作,但是,對於DataGridView這個奇葩的控制元件來說,這麼幹,DataGridView老是出一些奇葩錯誤。

最近寫一個程式,需要在另外一個執行緒中制定DataGridView的DataSource,但是按照如上方法,總是不能成功賦值。

因此,最後被逼無奈還是必須得用代理的方法了。

為了區別是否是建立該控制元件的執行緒訪問該控制元件,Windows窗體控制元件中的每個控制元件都有一個InvokeRequired屬性,這個屬性就是用來檢查本控制元件是否被其他執行緒呼叫的屬性,當被建立該執行緒外的執行緒呼叫的時候InvokeRequired就為true。有了這個屬性我們就可以利用它來做判斷了。 

  光判斷出是否被其他執行緒呼叫是沒有用的,所以windows窗體控制元件中還有一個Invoke方法可以幫我們完成其他執行緒對控制元件的呼叫。結合代理的使用就可以很好的完成我們的目標。

        private delegate void SetDGVSource(DataTable dt);//新增設定DataGridView的DataSource的代理
        public static void SetDGVSourceFunction(DataTable dt)
        {
            if (dataGridView1.InvokeRequired)
            {
                SetDGVSource delegateSetSource = new SetDGVSource(SetDGVSourceFunction);
                dataGridView1.Invoke(delegateSetSource, new object[] { dt });
            }
            else
            {
                dataGridView1.DataSource = dt;
            }
        }

然後,只需要在其他執行緒中呼叫SetDGVSourceFunction函式即可

注意,若其他執行緒在其他檔案,需要新增static屬性

另外,控制元件的InvokeRequired屬性以及Invoke屬性,都要求控制元件是靜態的。因此必須在Designer.cs檔案中,將dataGridView1的宣告前加上一個static,好了,問題來了,繼續報錯,這個時候,還需要將Designer.cs中的所有this.dataGridView1前面的this去掉即可

為了區別是否是建立該控制元件的執行緒訪問該控制元件,Windows窗體控制元件中的每個控制元件都有一個InvokeRequired屬性,這個屬性就是用來檢查本控制元件是否被其他執行緒呼叫的屬性,當被建立該執行緒外的執行緒呼叫的時候InvokeRequired就為true。有了這個屬性我們就可以利用它來做判斷了。 

  光判斷出是否被其他執行緒呼叫是沒有用的,所以windows窗體控制元件中還有一個Invoke方法可以幫我們完成其他執行緒對控制元件的呼叫。結合代理的使用就可以很好的完成我們的目標。