C# - 无法使用 Invoke() 从后台线程将文本追加到控件
本文关键字:线程 后台 文本 追加 控件 Invoke | 更新日期: 2023-09-27 17:56:25
问候,我在 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
....
它一直持续下去,"hello"消息没有打印出来,并且 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
原因是什么,我该怎么办?
提前谢谢。
Invoke
方法同步运行委托 - 它会等到 UI 线程实际运行它,然后再将控制权返回给调用方。
由于 UI 线程正在等待线程完成,因此会出现死锁。
相比之下,BeginInvoke
方法异步运行委托 - 它会立即返回,并且委托仅在一段时间后运行,当 UI 线程空闲时。
在离开 button1_Click
方法之前,您正在等待工作线程完成。这是一个问题,因为线程无法完成,直到它们能够在同一线程上运行调用 AppendText
方法的委托。
当您更改为 BeginInvoke
时,您不再遇到此问题,因为您的工作线程不会阻止等待调用 AppendText
方法的委托。
如果您尝试阻止 UI 线程直到工作线程完成,只要它们依赖于对 Invoke
的调用,您就根本无法做到。
您无法从其他线程更新 UI 控件,这是答案