Вопрос

У меня есть нерешенная проблема с потоками. Я делаю это впервые. Я знаю, как использовать один поток для записи в 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 () .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top