我对线程有一些未解决的问题。这是我第一次这样做。我知道如何使用一个线程在textBox中写入,但我不知道如何使用其中两个来完成这项工作。任何人都知道我需要做什么才能使用两个线程写入同一个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();
    }
}

其他提示

另一种选择是使用Thread Callback方法。这是主线程上存在的方法,但在创建新线程时,您将传递对此方法的句柄/引用。这允许第二个线程在主线程上调用该方法,并且更新/检查文本框的功能将在那里。

查看在线程之间传递委托。

您可以做的一个选项是将消息推送到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文章介绍了如何进行线程安全调用Windows窗体控件。

您只能从主线程访问GUI组件。要从另一个线程写入文本框,您需要使用 BeginInvoke()

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top