Запись в textBox с использованием двух потоков
-
03-07-2019 - |
Вопрос
У меня есть нерешенная проблема с потоками. Я делаю это впервые. Я знаю, как использовать один поток для записи в textBox, но я понятия не имею, как использовать два из них для выполнения работы. Любой знает, что мне нужно сделать, чтобы использовать два потока для записи в один и тот же текстовый блок, но не в одно и то же время. Спасибо.
Решение
Вот пример, который использует два потока для записи случайных чисел в многострочное текстовое поле. Как отметили Брэндон и Джон Б., вам нужно использовать Invoke () для сериализации вызовов в поток графического интерфейса.
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 и использовать таймер в форме окна для чтения сообщений из этой очереди и записи в текстовое поле.
Для того, чтобы все было хорошо и с потоками, вы можете заблокировать объект 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 поток, способный работать с текстовым полем (или любым объектом графического интерфейса), иметь любые другие потоки, которым необходимо выполнить действие с текстовым полем, и сообщать о своих потребностях потоку, управляющему текстом. коробка. Р>
Итак, ваш вопрос заключается в том, как взаимодействовать между потоками, это будет зависеть от языка / ОС, поэтому вам нужно предоставить больше информации.
В этой статье MSDN объясняется, как сделать потокобезопасными вызовы элементы управления окнами.
Вы можете получить доступ только к компонентам графического интерфейса из основного потока. Для записи в текстовое поле из другого потока необходимо использовать BeginInvoke () .