2011-07-19 30 views
3

我設法做出一個簡單的程序,從不同的線程和類更新文本框。以直觀的方式學習線程的最簡單方法。 ;)從一個線程調用工作,但不能做得更簡單?

該代碼是從MSDN的文檔。它運行,我看不到內存泄漏。但我有一種感覺,這可以做得更簡單。

有兩大類: Form和BackGround類。在BackGround類中有一個名爲generateStream的函數,它通過委託給一個名爲updateTextBox的函數更新Form類中的TextBox。

當buttonStart被按下時,會執行兩個操作。首先直接調用generateStream。當generateStream準備就緒時,會再次運行generateStream的線程(通過TheFunction)。當使用不同的線程時,TextBox需要一個調用解決方案。

所有這些都已經實施並且有效。我認爲這是相當多的代碼,也許可以做得更乾淨。

更新表單並被回調的主類中的函數。

public void updateTextBox(string strtext) 
    { 
     if (this.InvokeRequired) //When calling from another thread; invoke is required. 
     { 
      SetTextCallBack cb = new SetTextCallBack(updateTextBox); 
      this.Invoke(cb, new object[] { strtext }); 

     } 
     else //Call can be performed safely. 
     { 
      textBoxStatus.SelectionStart = textBoxStatus.Text.Length; 
      textBoxStatus.AppendText(strtext); 
      textBoxStatus.Update(); 
     } 
    } 

單擊按鈕完成的操作。

private void buttonStart_Click(object sender, EventArgs e) 
    { 
     buttonStart.Enabled = false; 

     /* 
     * Step 1: Let's call the function blocking. 
     *   The GUI will not respond to mouse geastures. Hoover mouse over inputbox to see no change in pointer. 
     */ 
     bg.generateStream(numberOfCalls, "GUI Thread: "); 


     /* 
     * Step 2: Let's call the function in a seperate thread. 
     *   The GUI will now respond to the mouse. Hoover mouse over inputbox to see pointer change. 
     */ 
     Thread sepThread = new Thread(new ThreadStart(this.TheFunction)); 
     sepThread.Start(); 

     buttonStart.Enabled = true; 
    } 

BackGround類中的generateStream函數。

public void generateStream(int amountOfStreams, string inpString) 
    { 
     for (int i = 0; i < amountOfStreams; i++) 
     { 
      Thread.Sleep(1000); //Easy does it. 
      myCallBack(inpString + i.ToString() + System.Environment.NewLine); //This is the text to the Main Form. 
     } 
    } 

當使用線程我現在使用兩個回調更新文本框。一個從BackGround類到Form,另一個用於實現Invoke。是否有例如沒有信號量解決方案可能我的updateTextBox函數只能有一個線程訪問?

+0

我不太明白你的問題是什麼,你可以嘗試用你的最後一段來解釋你的問題是什麼。 –

+0

你說得對,這是太多的文字,沒有方向。 – Joris

+0

作爲一個提示,你的主要問題'我認爲這是相當多的代碼,也許可以做得更乾淨.'應該放在帖子的底部而不是中間,所以它可以很容易地找到。 –

回答

3

當InvokeRequired爲true時,調用Invoke並沒有什麼壞處。我也喜歡在C#2.0中使用匿名方法。您可以簡化您的功能如下:

private delegate void SimpleProc(); 
private void updateTextBox(string strtext) { 
    this.Invoke(new SimpleProc(delegate() { 
     textBox1.SelectionStart = textBox1.Text.Length; 
     textBox1.AppendText(strtext); 
     textBox1.Update(); // only needed if updateTextBox is called from UI thread 
    }), null); 
} 

與BeginInvoke的更換援引是有用的一個發射後不管的情況下,在您不想後臺線程等待UI線程完成更新,但是您需要確定您的應用程序是否可用。

更新後的函數可以直接從UI線程或後臺線程調用。不需要回調;唯一使用的回調函數是updateTextBox中的匿名函數。它確實沒有比這更簡單。實際上,在很多情況下,創建調用UI線程的獨立函數並不是必須的。

+0

謝謝! 這已經節省了if語句的需要,並且使它更簡單。 我唯一支付的價格是總是額外的回調正在執行。 我在想像信號量。但直到現在我只能找到正確的方式來處理這個問題。 – Joris

+0

實際上,如果你從UI線程調用,Invoke將基本上做你原來的代碼做的事情,它直接調用你的回調函數而不會在消息隊列中發佈任何消息。這種情況下的性能影響可以忽略不計;調用只涉及一些額外的函數調用和代碼。我猜想,實際更新UI的回調代碼需要更多時間。如果從工作者線程調用Invoke,則自定義窗口消息將發佈到消息隊列中,以便將來在某個時候由UI線程處理。 –

相關問題