TextBox 和 RichTextBox 在线程方面的区别
Difference between TextBox and RichTextBox in regards to threading
我遇到了一个问题,我认为这可能是由于我 类 相互传递对象的复杂性,所以我将其最小化,但问题仍然存在:
我在 VS2017 社区中创建了一个默认的 winform 项目
我在表单上添加了一个文本框、一个富文本框、一个后台程序和一个用于激活后台程序的按钮。
我已将以下代码放入表单中以填充文本框并 运行 工作人员单击按钮:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
textBox1.Text = "Hello";
richTextBox1.Text = "World!";
}
private void button1_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy != true)
{
backgroundWorker1.RunWorkerAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
MessageBox.Show(textBox1.Text);
MessageBox.Show(richTextBox1.Text);
}
}
我运行这个程序,但我不明白接下来会发生什么。
textBox1.Text
可从表单访问,因此 MessageBox
显示正常。 richTextBox1.Text
无法访问并给我这个错误:
Cross-thread operation not valid: Control 'richTextBox1' accessed from a thread other than the thread it was created on.
为什么?
我假设 richTextBox 有更多的路由和包装,但是 .Text
属性 不完全一样吗?!这是怎么回事?
编辑: 我不认为这与标记的问题重复,因为他没有为 TextBox.Text
工作,而我的是。我问的是 TextBox 和 RichTextBox .Text 属性之间的差异。
你必须 Invoke
UI 代码(你不能 运行 UI 在除 UI 以外的线程中):
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// What to do with UI
Action action = () => {
MessageBox.Show(textBox1.Text);
MessageBox.Show(richTextBox1.Text);
}
if (InvokeRequired) // We are in some background thread, Invoke required
Invoke(action);
else // We are in UI (main) thread, just call the action
action();
}
它们的实施方式不同。
TextBox.Text
基本上 returns Control.Text
调用 WindowText
使用 GetWindowText
。
在代码注释中明确提到跨线程调用GetWindowText是可以的。所以他们通过设置标志inCrossThreadSafeCall
来故意关闭跨线程检查。
但是对于 ReachTextBox.Text
它不依赖于 Control.Text
。 It 发送 EM_STREAMOUT
并使用结果。所以没有标志被设置为除了这个来自跨线程异常。
注意: 你应该忽略这种情况,你永远不应该尝试从另一个线程访问 UI 元素。当您尝试从另一个线程与 UI 线程交互时,始终使用控件的 Invoke
方法。
我遇到了一个问题,我认为这可能是由于我 类 相互传递对象的复杂性,所以我将其最小化,但问题仍然存在:
我在 VS2017 社区中创建了一个默认的 winform 项目
我在表单上添加了一个文本框、一个富文本框、一个后台程序和一个用于激活后台程序的按钮。
我已将以下代码放入表单中以填充文本框并 运行 工作人员单击按钮:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
textBox1.Text = "Hello";
richTextBox1.Text = "World!";
}
private void button1_Click(object sender, EventArgs e)
{
if (backgroundWorker1.IsBusy != true)
{
backgroundWorker1.RunWorkerAsync();
}
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
MessageBox.Show(textBox1.Text);
MessageBox.Show(richTextBox1.Text);
}
}
我运行这个程序,但我不明白接下来会发生什么。
textBox1.Text
可从表单访问,因此 MessageBox
显示正常。 richTextBox1.Text
无法访问并给我这个错误:
Cross-thread operation not valid: Control 'richTextBox1' accessed from a thread other than the thread it was created on.
为什么?
我假设 richTextBox 有更多的路由和包装,但是 .Text
属性 不完全一样吗?!这是怎么回事?
编辑: 我不认为这与标记的问题重复,因为他没有为 TextBox.Text
工作,而我的是。我问的是 TextBox 和 RichTextBox .Text 属性之间的差异。
你必须 Invoke
UI 代码(你不能 运行 UI 在除 UI 以外的线程中):
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// What to do with UI
Action action = () => {
MessageBox.Show(textBox1.Text);
MessageBox.Show(richTextBox1.Text);
}
if (InvokeRequired) // We are in some background thread, Invoke required
Invoke(action);
else // We are in UI (main) thread, just call the action
action();
}
它们的实施方式不同。
TextBox.Text
基本上 returns Control.Text
调用 WindowText
使用 GetWindowText
。
在代码注释中明确提到跨线程调用GetWindowText是可以的。所以他们通过设置标志inCrossThreadSafeCall
来故意关闭跨线程检查。
但是对于 ReachTextBox.Text
它不依赖于 Control.Text
。 It 发送 EM_STREAMOUT
并使用结果。所以没有标志被设置为除了这个来自跨线程异常。
注意: 你应该忽略这种情况,你永远不应该尝试从另一个线程访问 UI 元素。当您尝试从另一个线程与 UI 线程交互时,始终使用控件的 Invoke
方法。