【问题标题】:C# - Cannot append text to control from background threads using Invoke()C# - 无法使用 Invoke() 将文本附加到后台线程的控件
【发布时间】:2011-08-26 03:27:09
【问题描述】:

您好,我在从 C# 中的工作线程调用 RichTextBox 时遇到问题。我正在使用 InvokeRequired/Invoke 方法。请看我的代码:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void ThreadSafe(MethodInvoker method)
    {
        if (InvokeRequired)
            Invoke(method);
        else
            method();
    }

    private void WorkerThread(object data)
    {
        string msg = "\nhello, i am thread " + data.ToString();
        ThreadSafe(delegate
        {
            richTextBox1.AppendText(msg);
        });
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Thread[] workers = new Thread[3];

        for (int i = 0; i < 3; i++)
        {
            workers[i] = new Thread(WorkerThread);
            workers[i].Start(i);
            string msg = "\nthread " + i.ToString() + "started!";
            richTextBox1.AppendText(msg);
        }

        int j = 3;
        while (j > 0)
        {
            for (int i = 0; i < 3; i++)
            {
                Thread.Sleep(250);
                richTextBox1.AppendText("\nChecking thread");
                if (workers[i].Join(250))
                {
                    string msg = "\nWorker thread " + i.ToString() + " finished.";
                    richTextBox1.AppendText(msg);
                    workers[i] = null;
                    j--;    // decrement the thread watch count
                }
            }
        }
    }
}

它在富文本框中打印以下内容:

thread 0started!
thread 1started!
thread 2started!
Checking thread
Checking thread
Checking thread
Checking thread
....

它继续,“你好”消息没有被打印,并且 UI 被冻结。 然后我把Invoke()改成了BeginInvoke(),我知道不应该这样做,结果是这样的:

thread 0started!
thread 1started!
thread 2started!
Checking thread
Worker thread 0 finished.
Checking thread
Worker thread 1 finished.
Checking thread
Worker thread 2 finished.
hello, i am thread 0
hello, i am thread 1
hello, i am thread 2

这是什么原因,我该怎么办?

提前致谢。

【问题讨论】:

    标签: c# multithreading user-interface controls invoke


    【解决方案1】:

    在离开 button1_Click 方法之前,您正在等待工作线程完成。这是一个问题,因为您的线程在能够运行在同一线程上调用AppendText 方法的委托之前无法完成。

    当您更改为BeginInvoke 时,您不再有此问题,因为您的工作线程不会阻塞等待调用AppendText 方法的委托。

    如果您试图阻塞 UI 线程,直到工作线程完成,只要它们依赖于对 Invoke 的调用,您就无法做到。

    【讨论】:

      【解决方案2】:

      Invoke 方法同步运行您的委托——它会等到 UI 线程实际运行它,然后再将控制权返回给调用者。
      由于 UI 线程正在等待您的线程完成,因此您会遇到死锁。

      相比之下,BeginInvoke 方法异步运行您的委托——它立即返回,并且委托仅在一段时间后运行,此时 UI 线程空闲。

      【讨论】:

        【解决方案3】:

        你不能从另一个线程更新 UI 控件,here is the answer

        【讨论】:

        • 他知道这一点。阅读问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-07
        • 2021-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多