【发布时间】:2009-05-01 18:29:13
【问题描述】:
我有一些未解决的线程问题。这是我第一次这样做。我知道如何使用一个线程在文本框中写入,但我不知道如何使用其中两个来完成这项工作。任何人都知道我必须做什么才能使用两个线程写入同一个文本框,但不能同时写入。谢谢。
【问题讨论】:
标签: c# .net multithreading textbox
我有一些未解决的线程问题。这是我第一次这样做。我知道如何使用一个线程在文本框中写入,但我不知道如何使用其中两个来完成这项工作。任何人都知道我必须做什么才能使用两个线程写入同一个文本框,但不能同时写入。谢谢。
【问题讨论】:
标签: c# .net multithreading textbox
这是一个使用两个线程将随机数写入多行文本框的示例。正如 Brandon 和 Jon B 所指出的,您需要使用 Invoke() 来序列化对 GUI 线程的调用。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Random m_random = new Random((int)DateTime.Now.Ticks);
ManualResetEvent m_stopThreadsEvent = new ManualResetEvent(false);
private void buttonStart_Click(object sender, EventArgs e)
{
Thread t1 = new Thread(new ThreadStart(ThreadOne));
Thread t2 = new Thread(new ThreadStart(ThreadTwo));
t1.Start();
t2.Start();
}
private void ThreadOne()
{
for(;;)
{
int n = m_random.Next(1000);
AppendText(String.Format("One: {0}\r\n", n));
if(m_stopThreadsEvent.WaitOne(n))
{
break;
}
}
}
private void ThreadTwo()
{
for(;;)
{
int n = m_random.Next(1000);
AppendText(String.Format("Two: {0}\r\n", n));
if(m_stopThreadsEvent.WaitOne(n))
{
break;
}
}
}
delegate void AppendTextDelegate(string text);
private void AppendText(string text)
{
if(textBoxLog.InvokeRequired)
{
textBoxLog.Invoke(new AppendTextDelegate(this.AppendText), new object[] { text });
}
else
{
textBoxLog.Text = textBoxLog.Text += text;
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
m_stopThreadsEvent.Set();
}
}
【讨论】:
另一种选择是使用线程回调方法。这是一个存在于主线程上的方法,但是当创建一个新线程时,您将一个句柄/引用传递给该方法。这允许第二个线程调用主线程上的方法,并且更新/检查文本框的功能将坐在那里。
查看线程之间的传递委托。
【讨论】:
您可以做的一个选择是将消息推送到 Queue 对象上,并使用 Windows 窗体上的计时器从该队列中读取消息并写入文本框。
为了让一切变得更好和线程化,您可以在读取和写入 Queue 对象时锁定它。
例如:
private Queue<string> messages = new Queue<string>();
/// <summary>
/// Add Message To The Queue
/// </summary>
/// <param name="text"></param>
public void NewMessage(string text)
{
lock (messages)
{
messages.Enqueue(text);
}
}
private void tmr_Tick(object sender, EventArgs e)
{
if (messages.Count == 0) return;
lock (messages)
{
this.textBox.Text += Environment.NewLine + messages;
}
}
【讨论】:
最安全的方法是只有 1 个线程能够处理文本框(或任何 gui 对象),让需要对文本框执行操作的任何其他线程将其需求传达给控制文本的线程盒子。
所以您的问题变成了如何在线程之间进行通信,这将是特定于语言/操作系统的,因此您需要提供更多信息。
【讨论】:
MSDN Article 解释了如何对 Windows 窗体控件进行线程安全调用。
【讨论】:
您只能从主线程访问 GUI 组件。要从另一个线程写入文本框,您需要使用BeginInvoke()。
【讨论】: