2012-08-26 80 views
3

我正在製作一個WinForms程序,它需要單獨的線程 爲了便於閱讀和可維護,我將所有非GUI代碼分隔到不同的類中。這個類還「生成」另一個類,它會進行一些處理。然而,我現在遇到了問題,我需要從一個不同的類中啓動的線程更改一個WinForms控件(追加一個字符串到文本框)從另一個線程更新WinForm控件_and_類

我已經搜索周圍,並找到不同線程的解決方案,並且在不同的班級,但不能同時和提供的解決方案顯得格格不入(對我來說)

這可能是最大的「鉛」但是:How to update UI from another thread running in another class

類層次結構示例:

class WinForm : Form 
{ 
    ... 
    Server serv = new Server(); 
} 

// Server is in a different thread to winform 
class Server 
{ 
    ... 
    ClientConnection = new ClientConnection(); 
} 

// Another new thread is created to run this class 
class ClientConnection 
{ 
    //Want to modify winform from here 
} 

我站在該事件處理是可能的路要走,但我不能工作,如何在這種情況下這樣做(我也接受其他的建議;))

任何幫助表示讚賞

回答

11

從哪個類要更新的形式沒關係輕鬆應對。 WinForm控件必須在與創建它們相同的線程上進行更新。

因此,Control.Invoke,允許您在自己的線程上對控件執行一個方法。這也稱爲異步執行,因爲調用實際上是排隊並單獨執行的。

看看這個article from msdn,這個例子與你的例子很相似。單獨的線程上的單獨的類更新窗體上的列表框。

-----更新 在這裏,您不必將此作爲參數傳遞。

在你的Winform類中,有一個公共委託可以更新控件。

class WinForm : Form 
{ 
    public delegate void updateTextBoxDelegate(String textBoxString); // delegate type 
    public updateTextBoxDelegate updateTextBox; // delegate object 

    void updateTextBox1(string str) { textBox1.Text = str1; } // this method is invoked 

    public WinForm() 
    { 
     ... 
     updateTextBox = new updateTextBoxDelegate(updateTextBox1); // initialize delegate object 
    ... 
    Server serv = new Server(); 

} 

從ClientConnection對象,你必須去在WinForm一個參考:Form對象。

class ClientConnection 
{ 
    ... 
    void display(string strItem) // can be called in a different thread from clientConnection object 
    { 
     Form1.Invoke(Form1.updateTextBox, strItem); // updates textbox1 on winForm 
    } 
} 

在上面的例子中,'this'沒有通過。

+0

這會很好,但它涉及到傳遞'this'作爲參數,我一直認爲如果你必須這樣做,你的程序結構就不好。我可能是完全錯誤的,但:) :) – LordAro

+0

你是對的,這是不是一個好主意,通過'這'作爲參數。在這裏,你沒有通過'這個'..請參閱更新的答案。 – shr

+0

這看起來不錯,謝謝,但還有一個問題:「...你必須獲得對WinForm:Form對象的引用。」 < - 怎麼樣? – LordAro