2011-02-08 54 views
8

我搜查了一噸,但我似乎無法找到與我的具體問題有關的任何事情。C#Windows窗體應用程序 - 從另一個線程和類更新GUI?

我想能夠從另一個類(SocketListener)更新我的MainUI形式,並且我有一個處理網絡(clientThread)的線程。現在我可以從網絡線程運行簡單的輸出,例如寫入調試器輸出並創建MessageBox。

但我真正想要做的就是能夠調用clientThread中的代碼,該代碼將在我的MainUI實例上執行。我怎樣才能做到這一點?

此外,如果有人想要代碼的特定部分,那麼我可以發佈它來幫助您更好地瞭解我所要求的內容。

此致敬禮!

回答

17

檢查Control類的InvokeRequired,如果這是真的,然後調用Invoke並傳遞,你想要給客戶端的線程上做一個委託(通常是匿名方法)。

例子:

public void DoWork(Form form) 
{ 
    if (form.InvokeRequired) 
    { 
     // We're on a thread other than the GUI thread 
     form.Invoke(new MethodInvoker(() => DoWork(form))); 
     return; 
    } 

    // Do what you need to do to the form here 
    form.Text = "Foo"; 
} 
+0

由於我處於與UI不同的類中,因此如何獲取指向當前正在運行的窗體以將其傳遞給DoWork的變量「form」? – 2011-02-08 00:18:52

+0

對於這種樣板文件,不會有一些AutoProperty類語法糖好嗎? – MusiGenesis 2011-02-08 00:20:38

4

是的,你可以添加一個構造函數類,是以MainUI形式作爲參數。這是實現它的快速方法,但它從您的類向MainUI引入了「向後」依賴關係,理論上,不需要依賴關係。

作爲一種替代方法,我會建議將一個公共事件添加到您的類中,然後MainUI表單可以訂閱。當你的類需要更新MainUI(或MainUI中的控件)時,該類將簡單地「引發」事件。這將調用在訂閱時註冊的MainUI方法。由於它是MainUI表單的一種方法,因此您只需更新窗體上的相應控件,並確保考慮到每個控件的InvokeRequired屬性。

而當這樣做,這是我一直在我的代碼中使用的構造。

class NetworkEventArgs : EventArgs { /* defined class here */ } 
private void NetworkEventHandler(object sender, NetworkEventArgs e) 
{ 
    Invoke((MethodInvoker) delegate { 
     myTextBox.Text = e.Message; 
    } 
} 

我已經在此博客上的文章here上。我沒有這種方法讓我失望,所以我沒有理由將我的代碼與InvokeRequired屬性的遞歸檢查複雜化。

0

您可以自定義事件的clientThread類

,並在MainForm的 處理它時clientThread需要知道的MainForm做一些事情(如更新一些控制狀態) 你應該火災的事件

這樣的MainForm得到來自事件和調用更新函數的參數

相關問題