[英]Inconsistent “Cross-thread operation not valid” exception
跨線程操作無效:控件''是從創建該線程的線程之外的線程訪問的。
我的同事在我的代碼上遇到此異常,但我沒有。
在表單上,我有一個控件,用戶可以在其中添加一些字符串到ListView。
我在控件中公開了一個屬性,該屬性返回XmlDocument中的字符串。
public XmlDocument XmlConfig
{
get
{
return GetXML();
}
}
獲取XML只是獲取ListViewItem集合並將其格式化為xml文檔。
private XmlDocument GetXML()
{
foreach(ListViewItem lvi in myListView.Items) <-- Exception Here
{
// Do Stuff
}
}
嘗試閱讀列表視圖時,為什么會得到這個? 我以為跨線程異常是當您嘗試從單獨的線程更新控件時。
為什么我也沒有得到這個例外?
我以為跨線程異常是當您嘗試從單獨的線程更新控件時
不對。 當不是從主UI線程訪問控件時,就會發生跨線程異常。 解決方案很簡單,請檢查InvokeRequired
並使用Invoke
。
至於為什么你的朋友打了這個而你卻不打呢,這不可能從你發布的代碼中看出來。 可能是他針對不同的.Net目標版本進行了編譯,也可能是您的硬件受到打擊的競爭條件(例如,他擁有更多的內核)。 一點是無關緊要的。 您的代碼必須是線程安全的,顯然GetXML
可以並且是從非主UI線程調用的。 檢查InvokeRequired
的責任很可能應該在調用方上,而不是在方法上。 同樣,從發布的代碼中無法分辨。
當在非UI線程中訪問Control
時( InvokeRequired
返回true
),應該使用Invoke
insetead直接調用; 為了不重復代碼(對於UI線程和其他線程),我們使用擴展方法:
private XmlDocument GetXML() {
myListView.InvokeSynchronized(() => {
foreach(ListViewItem lvi in myListView.Items) {
// Do Stuff
}
});
}
...
public static class ControlAsyncExtensions {
public static void InvokeSynchronized(this Control control, Action action) {
if (Object.ReferenceEquals(null, action))
throw new ArgumentNullException("action");
if (Object.ReferenceEquals(null, control))
action();
else if (control.InvokeRequired)
control.Invoke(action);
else
action();
}
}
我以為跨線程異常是當您嘗試從單獨的線程更新控件時。
那是不對的。 請記住,大多數WinForms控件都是Windows通用控件的包裝 。 Windows控件通常通過SendMessage函數將消息用於檢索和更新。 因此,通常來說,盡管可以安全地從其他線程執行某些調用,但是出於安全原因, Control.CheckForIllegalCrossThreadCalls用於每個get / set屬性或方法調用的控件實現中。
為什么我也沒有得到這個例外?
沒關系,您不應該一開始就這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.