2009-11-30 114 views
0

爲了與線程,委託人和背景工作人員一起玩,我正在編寫一些小應用程序,我在其中一個小問題上遇到了一些麻煩。 我有一個Windows窗體,有一個文本框,一個按鈕和一個richttext。 當我按下按鈕,文本框中的文本被用作參數設置爲實例化一個類,如下所示:C#線程問題

public partial class Form1 : Form 
{ 
    private BackgroundWorker backgroundWorker; 

    public Form1() 
    { 
     InitializeComponent();    
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     backgroundWorker = new BackgroundWorker(); 
     backgroundWorker.DoWork += new DoWorkEventHandler(worker_DoWork); 
     backgroundWorker.RunWorkerAsync(); 
    } 

    void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     new Thread((ThreadStart)delegate() 
     { 
      this.BeginInvoke((ThreadStart)delegate() 
      { 
       foreach (string line in textBox1.Lines) 
       { 
        Dig digger = new Dig(line, textBox1.Text); 
        digger.DomainChecked += new Dig.DomainCheckedHandler(OnUpdateTicker); 

        string response = digger.GetAllInfo(); 

        richTextBox1.AppendText(response); 
        Application.DoEvents(); 
       } 
      }); 
     }).Start(); 
    } 

    void OnUpdateTicker(string msg) 
    { 
     new Thread((ThreadStart)delegate() 
     { 
      this.BeginInvoke((ThreadStart)delegate() 
      { 
       label4.Text = msg; 
       Application.DoEvents(); 
      }); 
     }).Start();    
    } 
} 

當調試我碰上「textBox1.Lines」投擲類型的異常' Microsoft.VisualStudio.Debugger.Runtime.CrossThreadMessagingException' 有關如何解決此問題的任何提示?

回答

5

首先,沒有必要在DoWork內創建新線程;與BackgroundWorker的整個想法是DoWork在一個單獨的線程上執行。其次,由於DoWork在單獨的線程上執行,並且UI控件只能在UI線程上修改,所以需要正確調用這些更新。所以,worker_DoWork重寫版本看起來是這樣的:

void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    foreach (string line in textBox1.Lines) 
    { 
     Dig digger = new Dig(line, textBox1.Text); 
     digger.DomainChecked += new Dig.DomainCheckedHandler(OnUpdateTicker); 
     string response = digger.GetAllInfo(); 
     richTextBox1.Invoke((Action) delegate { richTextBox1.AppendText(response); }); 
    } 
} 

注意如何代碼中並沒有明確派生的任何新主題,也是AppendText方法調用是如何完成通過Control.Invoke呼叫,迫使其執行上UI線程。

0

主要原因是文本框不屬於後臺線程。

你的用戶界面線程擁有所有的用戶界面對象,並且當按下按鈕時你將旋轉後臺線程。該後臺線程不應該有權訪問任何UI對象。

如果您希望使用文本框的值,則需要以另一種方式將它傳遞給後臺線程。

Have a look here for an explanation (and solution).

0

只能從主線程本身在主線程上更新控制,除非你明確告訴你的程序,這是確定的事情,通過使用控制的.Invoke方法。

From: http://www.albahari.com/threading/part3.aspx 

Control.Invoke

在多線程Windows窗體應用程序,這是非法的調用方法或屬性從不同於創建它的一個其他任何線程控制。所有跨線程調用都必須使用Control.Invoke或Control.BeginInvoke方法顯式編組到創建控件的線程(通常是主線程)。一個人不能依靠自動編組,因爲它發生得太遲 - 只有當執行進入非託管代碼時,很多內部.NET代碼可能已經在「錯誤」的線程上運行 - 這是非線程安全的代碼。