我遇到了一个问题,我认为这可能是由于我的类将对象彼此传递的复杂性所致,所以我将其最小化,问题仍然存在:
我在VS2017社区中创建了一个默认的winform项目
在表单上,我添加了一个文本框,一个richtextbox,一个backgroundworker和一个用于激活background worker的按钮。
我将以下代码放入表单中,以填充文本框并在单击按钮时运行工作程序:
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
无法访问,并给我这个错误:
跨线程操作无效:控制'richTextBox1'是从创建该线程的线程之外的其他线程访问的。
为什么?
我假设richTextBox具有更多的路由和换行功能,但是.Text
属性是否不完全相同?这是怎么回事?
编辑:我不认为这与已标记的问题重复,因为他不是为TextBox.Text
工作,而我是。我在问TextBox和RichTextBox .Text属性之间的区别。
答案 0 :(得分:8)
它们的实现方式有所不同。
TextBox.Text
基本上返回Control.Text
,后者调用使用GetWindowText
的{{3}}。
在代码注释中明确提到的可以调用GetWindowText跨线程。因此,他们通过设置标志inCrossThreadSafeCall
来关闭有意检查跨线程的功能。
但是对于ReachTextBox.Text
,它不依赖Control.Text
。 WindowText
发送EM_STREAMOUT
并使用结果。因此,除了跨线程异常外,没有其他任何标志设置。
注意::您应该忽略这种情况,并且永远不要尝试从另一个线程访问UI元素。尝试与另一个线程中的UI线程进行交互时,请始终使用控件的Invoke
方法。
答案 1 :(得分:1)
您必须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();
}