none
在multiThread的情況下,從類別中,更新表單(Form): RRS feed

  • 問題

  • 在multiThread的情況下,從類別中,更新表單(Form):

    我在Form中,宣告了Thread,並傳入我設計的(物件方法)
    但是我需要在物件方法中更新表單~的label

    平常在Form當中,是沒有問題的
    宣告一個方法裡面有著更新UI的code,然後利用delegate,即可以更新UI

    但是,這次,我要在“物件的方法“ 執行過程中更新,試過了好多方式,都沒辦法更新~“~完全沒反應

    不知道有網友有相關的經驗嗎?
    謝謝~~“~
    2009年1月5日 下午 09:04

解答

  • 你的問題需要SourceCode才能幫你確認.

    但給個建議

    以物件導向設計

    請將邏輯與資料分開處理,所以依你的敘述就犯了一個錯誤將Control當作參數傳遞.

    寫多工緒程式時最好遵守這個原則可以避免掉許多麻煩,多工緒是很難模擬出環境來找出問題的.

    多工緒程式的好壞重點不單單只是技術上,更重要的是架構上.

     

    譬如 底下就不是個好寫法

    Code Snippet

    class UpdateDate

    {

    private Label _lbl;

    public UpdateLabel(Label lbl)

    {

    this._lbl = lbl;

    }

     

    public void Update()

    {

    bool result;

    .....處理運算

    if(result )

    this.Label1 = "成功";

    else

    this.Label1 = "失敗";

    }

    }

     

     

    class MainForm : From

    {

    UpdateDate u = new UpdateDate(this.Label1);

    u.Update();

    }

     

     

    應該改為

    Code Snippet

    class UpdateDate

    {

    public UpdateLabel()

    {

    }

     

    public bool Update()

    {

    bool result;

    .....處理運算

    return result;

    }

    }

     

     

    class MainForm : From

    {

    UpdateDate u = new UpdateDate();

    bool result = u.Update();

    if(result )

    this.Label1 = "成功";

    else

    this.Label1 = "失敗";

    }

     

     

     

    如用第一種方式遇到多工緒的問題就會導致程式變為混亂因為程式在處理資料的class處理UI問題

    但若是第二種就可以將UI的更新都放置到Form的程式碼中.

    2009年1月6日 上午 05:30

所有回覆

  • 物件的方法也要呼叫 delegate 啊。

    你的 Thread 起始應該是呼叫物件的方法,但你的物件的方法中有呼叫那個 delegate 嗎?

     

    2009年1月6日 上午 12:05
  • 因為你目前所在的物件方法與你要更新的UI並不是在同一個Thread中,所以你必須在物件方法中切回要更新的UI所在Thread.

    SampleCode如下

     

     

    Code Snippet

    private delegate void IncpbParseLogValueInvoke(string result);
    private void ParseLogForm_IncpbParseLogValue(string result)
    {

                //判斷目前所在Thread是否與lblText Control相同  
                if (lblText.InvokeRequired)
                {

                    //不是的話,使用Control.Invoke切回Control所在的Thread
                    lblText.Invoke(new IncpbParseLogValueInvoke(this.ParseLogForm_IncpbParseLogValue), result);
                }
                else
                {
                   //Control更新如

                   lblText.Text = "更新";

                }
    }

     

     

     

    2009年1月6日 上午 12:43
  • 恩!謝謝~
    我自己也找到一篇
    從工作執行緒中操作UI
    我也實作成功了~~(開一個新的專案實作)

    但是,弔詭的是,在我原本的專案中,我的Label,竟然無法更新!
    我把thread拿掉了,還是沒辦法更新

    我將label傳進類別的建構子當中,然後在建構子中改變label.Text,也確認過,值的確有進去,但是
    就是沒辦法更新~“~

    label1.Text = "123123"; ->這是我存進去的值

    但是,我覺得這真的太詭異了!

    所以,我又寫了一個 button,裡面放著MessageBox.Show(label.Text);

    答案是,沒有值!!

    不知道有沒有人碰過這種詭異的情況......
    2009年1月6日 上午 05:14
  • 你的問題需要SourceCode才能幫你確認.

    但給個建議

    以物件導向設計

    請將邏輯與資料分開處理,所以依你的敘述就犯了一個錯誤將Control當作參數傳遞.

    寫多工緒程式時最好遵守這個原則可以避免掉許多麻煩,多工緒是很難模擬出環境來找出問題的.

    多工緒程式的好壞重點不單單只是技術上,更重要的是架構上.

     

    譬如 底下就不是個好寫法

    Code Snippet

    class UpdateDate

    {

    private Label _lbl;

    public UpdateLabel(Label lbl)

    {

    this._lbl = lbl;

    }

     

    public void Update()

    {

    bool result;

    .....處理運算

    if(result )

    this.Label1 = "成功";

    else

    this.Label1 = "失敗";

    }

    }

     

     

    class MainForm : From

    {

    UpdateDate u = new UpdateDate(this.Label1);

    u.Update();

    }

     

     

    應該改為

    Code Snippet

    class UpdateDate

    {

    public UpdateLabel()

    {

    }

     

    public bool Update()

    {

    bool result;

    .....處理運算

    return result;

    }

    }

     

     

    class MainForm : From

    {

    UpdateDate u = new UpdateDate();

    bool result = u.Update();

    if(result )

    this.Label1 = "成功";

    else

    this.Label1 = "失敗";

    }

     

     

     

    如用第一種方式遇到多工緒的問題就會導致程式變為混亂因為程式在處理資料的class處理UI問題

    但若是第二種就可以將UI的更新都放置到Form的程式碼中.

    2009年1月6日 上午 05:30
  • 恩!謝謝你的答覆~~~
    不過,這兩天寫了一下,還是解不出“將Control當作參數傳遞“.

    我想到一個解法,就是在類別裡面宣告Form1 f1 = new Form1();
    並在Form類別裡面設置更新的function like 

    public void UpdateUI(string value)
    {
    label1.Text = value;
    }

    然後,在類別裡面使用delegate 
    呼叫f1.UpdateUI()
    可以run
    但是無法更新~~"~

    所以實驗結果失敗~“~



    2009年1月7日 下午 09:05
  • 能否將你的程式碼PO上

    另外說明你的需求.

     

    2009年1月7日 下午 11:59