我无法相信以前没有问过这个问题,但我在这里找不到参考资料。对不起,如果我错过了!!从线程更新rtb.Text有很多,但很少或没有获取rtb.Text。
我需要从另一个线程的UI线程上的richtextbox获取文本值,然后才能遍历同一个richtextbox的每一行。
我猜Invokes和Delegates是必需的,但是如何制作它们?
作为示例,如果代码位于同一个线程中,则代码类似于:
private void checkRtbEntries()
{
if (rtb.Text != "")
{
foreach (string textLine in rtb.Lines)
{
// do some things in the background thread
// based on the rtb line content...
}
}
}
但是,在Backgroundworker线程中调用checkRtbEntries(),并且rtb在UI线程中,因此抛出了无效的跨线程操作。
答案 0 :(得分:3)
运行BackgroundWorker线程时,可以选择将参数传递给它,另一个线程可以引用该参数并使用:
myWorker.RunWorkerAsync(rtb.Text);
在DoWork
事件中,将参数强制转换为字符串并对其执行操作。
var myRtbText = e.Argument.ToString();
这样,您的后台线程实际上从未触及UI线程。
如果您需要在后台工作人员运行时对主线程上的元素进行更改,则需要使用ProgressChanged
事件。
由于您没有RichTextBox
事件中DoWork
的引用(只是Text
属性的内容),因此您实际上无法调用{{1原始文本框上的属性。
你应该能够很容易地模拟它(实际的Lines
属性测试“\ r”,“\ r \ n”和“\ n”,但Lines
应该采取关心为你解决这个问题):
Environment.NewLine
(如果要忽略空行,请使用StringSplitOptions.RemoveEmptyEntries。)
答案 1 :(得分:1)
这是从后台跳转到UI线程(对于每个控件)的常用方法
private delegate void checkRichTextBoxDelegate();
private void checkRtbEntries()
{
if (this.rtb.InvokeRequired)
{
checkRichTextBoxDelegate checkEntries = new checkRichTextBoxDelegate(checkRtbEntries);
this.Invoke(checkRtbEntries);
}
else
{
.... do your work on the RichTextBox, you are on the UI thread
}
}