2011-03-11 30 views
7

我有一個主UI線程運行應用程序並創建主窗口窗體(我們稱之爲W)。我還有一個輔助線程,我旋轉起來並創建一個對話框(我們稱之爲B)。設置WinForms.Form所有者時出現跨線程異常 - 如何正確執行?

我想將對話框B的所有者設置爲主窗口W。所有者的設置B發生在創建B的線程上。基本上是:

b.Owner = w; 

但這拋出一個跨線程異常告訴我,我tryng從錯誤的線程訪問W對象。

所以我試圖通過使用W上的Control.Invoke來執行主UI線程上的代碼。但後來,我得到了同樣的錯誤,告訴我,我從錯誤的線程試圖訪問B

System.InvalidOperationException was unhandled by user code 
    Message=Cross-thread operation not valid: Control 'B' accessed from a 
    thread other than the thread it was created on. 
    Source=System.Windows.Forms 

我怎麼做是正確的?

+0

不要在多個線程上使用窗體。它會給你更多的麻煩,而不是它的價值。 – SLaks 2011-03-11 13:51:28

+0

你讀過這個SO帖子:http://stackoverflow.com/questions/3046245/whats-wrong-with-my-cross-thread-call-in-windows-forms?如果這沒有幫助你,你應該發佈代碼給你的錯誤。 – 2011-03-11 13:51:29

+0

也許您可以告訴我們您希望利用哪些所有權特徵(希望不是所有),並且我們可以建議實現類似效果的方法? – 2011-03-11 14:05:17

回答

5

這是Winforms中的一個bug,Windows實際上支持讓所有者成爲另一個線程創建的窗口。有一種方法可以禁用該檢查,您應該從來沒有做。除非你有我猜想:

private void button1_Click(object sender, EventArgs e) { 
     var t = new Thread(() => { 
      Control.CheckForIllegalCrossThreadCalls = false; 
      var frm = new Form2(); 
      frm.Show(this); 
      Control.CheckForIllegalCrossThreadCalls = true; 
      Application.Run(frm); 
     }); 
     t.SetApartmentState(ApartmentState.STA); 
     t.Start(); 
    } 

我做知道這是100%安全的,有可能是一個WinForms交互時螺絲的東西了。你在這裏沒有經過檢驗的水域,被穿線鯊魚感染。

+0

你的建議很有趣。就我而言,我可以確保顯示對話框的代碼不會干擾主UI線程。我會試一試。 – 2011-03-12 21:45:32

+2

你是否發現了有關上述方法安全的更多信息?我想這樣做(有一個表單擁有一個綁定到不同線程的表單),但需要注意兩點:(1)顯示另一個表單將會調用「Owner.AddOwnedForm」,該表單可能不是線程化的,安全;更好地對所有者窗體的線程執行操作; (2)如果綁定到不同線程的兩個表單試圖同時顯示自己,那麼可以在另一個線程將其設置爲false的時間與執行該操作的時間之間設置「CheckForIllegalCrossThreadCalls = true」,以使其爲false。 – supercat 2013-06-19 18:25:25

3

B需要在UI線程上創建。

您仍然可以通過使用Control.Invoke從輔助線程與B進行交互。

+0

在我的情況下,它不適用於我打算做的事情:如果主UI線程被阻塞工作,我的'B'窗口將不會更新。 – 2011-03-12 21:43:37

2

如果你實際上在不同的線程上運行兩個消息循環,那麼你就沒有辦法做你以後的事情。如果你想W擁有B,你將不得不在主線程上創建B,並且在第二個線程中你需要與B進行所有的交互Invoke

相關問題