2011-05-16 97 views
1

問候,我有問題從C#中的工作線程調用richTextBox。我正在使用InvokeRequired/Invoke方法。請參閱我的代碼:C# - 不能附加文本控制從後臺線程使用Invoke()

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void ThreadSafe(MethodInvoker method) 
    { 
     if (InvokeRequired) 
      Invoke(method); 
     else 
      method(); 
    } 

    private void WorkerThread(object data) 
    { 
     string msg = "\nhello, i am thread " + data.ToString(); 
     ThreadSafe(delegate 
     { 
      richTextBox1.AppendText(msg); 
     }); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     Thread[] workers = new Thread[3]; 

     for (int i = 0; i < 3; i++) 
     { 
      workers[i] = new Thread(WorkerThread); 
      workers[i].Start(i); 
      string msg = "\nthread " + i.ToString() + "started!"; 
      richTextBox1.AppendText(msg); 
     } 

     int j = 3; 
     while (j > 0) 
     { 
      for (int i = 0; i < 3; i++) 
      { 
       Thread.Sleep(250); 
       richTextBox1.AppendText("\nChecking thread"); 
       if (workers[i].Join(250)) 
       { 
        string msg = "\nWorker thread " + i.ToString() + " finished."; 
        richTextBox1.AppendText(msg); 
        workers[i] = null; 
        j--; // decrement the thread watch count 
       } 
      } 
     } 
    } 
} 

它打印在豐富的文本框中鍵入以下:

thread 0started! 
thread 1started! 
thread 2started! 
Checking thread 
Checking thread 
Checking thread 
Checking thread 
.... 

它的推移而上,在「你好」消息沒有得到打印,用戶界面是凍結。 然後,我改變調用()來的BeginInvoke(),我知道我不應該這樣做,那麼結果是這樣的:

thread 0started! 
thread 1started! 
thread 2started! 
Checking thread 
Worker thread 0 finished. 
Checking thread 
Worker thread 1 finished. 
Checking thread 
Worker thread 2 finished. 
hello, i am thread 0 
hello, i am thread 1 
hello, i am thread 2 

的原因是什麼和怎麼辦?

在此先感謝。

回答

1

您正在等待工作線程離開button1_Click方法之前完成。這是一個問題,因爲只有當它們能夠運行在同一線程上調用AppendText方法的委託時,線程才能完成。

當您更改爲BeginInvoke時,您不再有此問題,因爲您的工作線程不會阻止等待調用AppendText方法的委託。

如果您是嘗試來阻止UI線程,直到工作線程完成爲止,只要它們依賴於對Invoke的調用即可。

-1

您不能從另一個線程更新UI控件,here is the answer

+2

他知道這一點。閱讀問題。 – SLaks 2011-05-16 02:48:43

5

Invoke方法同步運行您的委託—它等到UI線程實際運行它之後纔將控制權返回給調用方。
由於UI線程正在等待線程完成,所以會發生死鎖。

相比之下,BeginInvoke方法異步運行您的代理—它立即返回,並且委託僅在稍後運行,當UI線程空閒時。