我不敢相信以前没有问过这个问题,但我在这里找不到参考资料。对不起,如果我错过了!!有很多关于更新 rtb 的内容。来自线程的文本,但在获取 rtb 时很少或没有。发短信。
我需要从另一个线程的 UI 线程上的富文本框中获取文本值,然后能够遍历同一富文本框的每一行。
我想调用和委托是必需的,但如何制作它们?
例如,如果代码位于同一线程中,则如下所示:
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...
}
}
}
但是,checkRtbEntries() 是从 Backgroundworker 线程中调用的,而 rtb 在 UI 线程中,因此抛出无效的跨线程操作。
运行 BackgroundWorker 线程时,可以选择向其传递参数,其他线程可以引用和使用参数:
myWorker.RunWorkerAsync(rtb.Text);
在 DoWork
事件中,将参数强制转换为字符串并对其执行操作。
var myRtbText = e.Argument.ToString();
这样,您的后台线程实际上永远不会接触 UI 线程。
如果需要在后台工作线程运行时对主线程上的元素进行更改,则需要使用 ProgressChanged
事件。
由于在 DoWork
事件中没有对RichTextBox
的引用(只有其 Text
属性的内容),因此实际上无法在原始文本框上调用 Lines
属性。
不过,您应该能够非常轻松地模拟它("\r"、"\r"和""的实际Lines
属性测试,但Environment.NewLine
应该为您解决这个问题):
var allLines
= myRtbText.Split(new[] {Environment.NewLine}, StringSplitOptions.None);
(如果要忽略空行,请使用 StringSplitOptions.RemoveEmptyItems。
这是从后台跳转到 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
}
}