在C#中使用另一个类的表单中的文本框

时间:2009-10-14 03:27:49

标签: c# textbox multithreading

所以我有

public class Form1 : Form {}

class Updater {}

我在Form1上有textBox1,以及许多其他控件......

所以这就是我的困境:我在Updater中有一个while(true) {}循环,我无法将它粘贴在Form1类中,因为它阻止了表单的加载。我需要在Updater上更新Form1上的多行文本框(textBox1)。 Updater是一个TCP客户端,当它收到信息时,我需要将其信息+=放入文本框中。但是如何从不同于创建文本框的线程中访问文本框?

编辑:我正在寻找代码示例。

3 个答案:

答案 0 :(得分: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;
    }   

答案 1 :(得分:1)

如果Form1引用了Updater,那么您可以在Form1可以订阅的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");
                }
            }
        }

    }

答案 2 :(得分: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;
    }