我正在處理一個大型應用程序(獲得跨線程異常)時遇到了一些線程問題。有沒有辦法找到創建特定控件的線程名稱/ ID?有沒有辦法找到控件的所有者線程?
當我嘗試向控件的控件集合添加新控件時發生此錯誤。我不能真正創建一個小的,可重複的樣本,所以我會盡我所能地描述它。
我有一個坐在窗體上的主控件,稱之爲_mainControl。在它的構造我實例化另一個控制的一個實例,像
ChildControl _childControl = new ChildControl();
現在_childControl存在,但我不把它添加到_mainControls最愛。
最後,_mainControl接收到一個事件通知,我應該添加該控件。在事件處理我檢查this.InvokeRequired,如果是,我調用處理程序,類似如下:
AddControlEventHander(...)
{
if(InvokeRequired)
{
BeginInvoke(new MethodInvoker(AddControlEventHander);
return;
}
Controls.Add(_childControl);
}
唯一的例外是在Controls.Add被(「跨線程操作無效,始終拋出:控制'_item'從其創建線程以外的線程訪問「)。
現在,我不明白的是這是如何可能的。我在創建_mainControl的同一個線程上創建_childControl。當我在調試時查看線程窗口時,當我調用Control.Add時,當前線程名稱/ ID與添加_childControl時相同。但是,最讓我困惑的是來自_mainControl的以下調用:
InvokeReuqired == false;
_childControl.InvokeRequired == false;
_childControl._item.InvokeRequired == true; //I made _item public just to try this and it returns true!
這怎麼可能?是否有可能在一個線程上創建_childControl,而在另一個線程上創建子控件?正常情況下,_childControl的所有子項都是在初始化過程中創建的。
如果任何人有任何提示/建議可能會發生什麼,請讓我知道。
謝謝。
編輯:
如果有人有興趣,我發現發生了什麼事。我很好奇如何在一個線程上創建一個控件,並且它是在另一個線程上創建的子類,即使InitializeComponent都是在同一個線程上完成的。因此,我使用類似於Charles在下面提出的代碼來找出創建哪個線程。一旦我知道了,我至少知道應該關注哪個線程。然後我打破了兒童控制的OnHandleCreated事件,發現了這個問題。
我不知道的一件事是控件的句柄是在控件第一次變得可見時創建的,而不是在創建時創建的。所以一個沒有控制權的線程試圖將它的可見性設置爲true。所以我添加了一張支票,看看InvokeRequired是否可以實現。然而,我真的沒有想到的是,調用InvokeRequired將創建控件的句柄,如果它尚未創建!這實際上導致控制被創建在錯誤的線程上,並且總是爲InvokeRequired返回false。我通過觸摸控件的Handle屬性來解決此問題,以便在調用InvokeRequired之前創建該屬性。
感謝您的幫助球員:)
感謝您的提示。我同樣發現無害的'if(control.Handle!= null)...'實際上創建了該線程上的控件! – 2013-06-11 21:48:39
在這裏看到我的答案http://stackoverflow.com/questions/8331144/ensuring-that-child-controls-are-created-in-main-ui-thread/17054689#17054689 – 2013-06-11 22:09:43