2009-10-14 30 views
0

所以我從另一個類工作在形式的文本框,在C#

public class Form1 : Form {} 

class Updater {} 

而且我有textBox1的Form1上,與許多其他控件一起...

所以這裏是我的困境:我在Updater中有一個while(true) {}循環,並且我無法將它粘在Form1類中,因爲它阻止了表單的加載。我需要從更新程序更新Form1上的多行文本框(textBox1)。更新程序是一個TCP客戶端,當它接收到信息時,我需要它將它的信息輸入到文本框中。但是,如何從與它創建的線程不同的線程訪問文本框?

編輯:我正在尋找代碼示例,請。

+0

不Form1中有一個參考,以更新? – CSharpAtl

回答

2

你爲什麼不聲明在Updater類的事件?然後,您可以在從TCP獲取數據時引發此事件。

public class Updater 
{ 
    public delegate void DataReceivedEventHandler(object sender,DataEventArgs e); 
    public event DataReceivedEventHandler DataReceived = delegate { }; 

    public void ReadData() 
    { 
     //here you will get data from what ever you like 
     //upon recipt of data you will raise the event. 

     //THIS LOOP IS FOR TESTING ONLY 
     for (var i = 1; i < 101; i++) 
     { 
      //PASS REAL DATA TO new DataEventArgs 
      DataReceived(this, new DataEventArgs("Event " + i)); 
      Thread.Sleep(500); 
     } 
    } 
} 

public class DataEventArgs : EventArgs 
{ 
    public string Data { get; set; } 
    public DataEventArgs(string data) : base() 
    { 
     Data = data; 
    } 
} 

在你形成:

//you will setup "Updater" in some else way. I've written this function 
    //which I call on a button click for testing 
    private void Init() 
    { 
     var u = new Updater(); 
     u.DataReceived += delegate(object sender, DataEventArgs e) 
           { SetTextboxText(e.Data); }; 

     BackgroundWorker bw = new BackgroundWorker(); 

     bw.DoWork += delegate(object sender, DoWorkEventArgs e) 
       { ((Updater)e.Argument).ReadData(); }; 
     bw.RunWorkerAsync(u); 
    } 

    private void SetTextboxText(string s) 
    { 
     if (TEXT_BOX.InvokeRequired) 
     { 
      //This techniques is from answer by @sinperX1 
      BeginInvoke((MethodInvoker)(() => { SetTextboxText(s); })); 
      return; 
     } 
     TEXT_BOX.Text += Environment.NewLine + s; 
    } 
+0

我已添加新代碼。它的作品我測試過了。 – TheVillageIdiot

1

如果Form1具有對Updater的引用,則可以將事件放在F​​orm1可訂閱的Updater類上。當Updater具有數據(或者需要更新表單的任何理由)時,它設置事件,表單捕獲事件並更新文本框。

實施例:當一個線程用於訪問沒有創建控制的控制

public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
      Updater textboxUpdater = new Updater(); 
      textboxUpdater.Updated += s => {textBox1.Text = s;}; 
     } 
    } 


public class Updater 
    { 
     public delegate void UpdateEventHandler(string eventName); 
     public event UpdateEventHandler Updated = delegate { }; 

     private bool needUpdating; 
     public void Process() 
     { 
      while (true) 
      { 
       //Processing 
       if (needUpdating) 
       { 
        Updated("something"); 
       } 
      } 
     } 

    } 
+0

需要注意的一件事:更新程序會在自己的(後臺)線程上引發事件。因此,無論是事件提升者還是事件處理程序,都需要使用Nate描述的技術將其整理到文本框的線程中。 – itowlson

1

跨線程的原因。爲了解決它,你調用。

http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx

例子:

/// <summary> 
    /// This is a thread safe operation. 
    /// </summary> 
    /// <param name="text"></param> 
    public void SetTextBoxText(string text) 
    { 
     if (InvokeRequired) 
     { 
      Invoke((MethodInvoker)delegate { SetText(text); }); 
      return; 
     } 

     // To get to this line the proper thread was used (by invoking) 
     myTextBoxt.Text += text; 
    } 

    /// <summary> 
    /// This is an alternative way. It uses a Lambda and BeginInvoke 
    /// which does not block the thread. 
    /// </summary> 
    /// <param name="text"></param> 
    public void SetTextBoxText(string text) 
    { 
     if (InvokeRequired) 
     { 
      BeginInvoke((MethodInvoker)(() => { SetText(text); })); 
      return; 
     } 

     // To get to this line the proper thread was used (by invoking) 
     myTextBox.Text += text; 
    } 
相關問題