訪問 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方法可以幫我們完成其他線程對控件的調用。結合代理的使用就可以很好的完成我們的目標。
---------------------
作者:celte
來源:CSDN
原文:https://blog.csdn.net/celte/article/details/9304939?utm_source=copy
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
