所以我有
public class Form1 : Form {}
和
class Updater {}
我在Form1上有textBox1,以及许多其他控件......
所以这就是我的困境:我在Updater中有一个while(true) {}
循环,我无法将它粘贴在Form1类中,因为它阻止了表单的加载。我需要在Updater上更新Form1上的多行文本框(textBox1)。 Updater是一个TCP客户端,当它收到信息时,我需要将其信息+=
放入文本框中。但是如何从不同于创建文本框的线程中访问文本框?
编辑:我正在寻找代码示例。
答案 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;
}