如何从另一个线程调用控制方法

我想从另一个线程调用RichTextBox.Find() 。 我怎样才能做到这一点? RichTextBox位于我在表单中使用的UserControl中。 我想从另一个线程更新它。 我能够使用Invoke更改其属性。 但无法弄清楚如何调用_ucResultRich.rchResult.Find(word, startIndex, RichTextBoxFinds.None); 从我的线程。

 Thread thread=new Thread(thrHighlight); thread.Start(e.RowIndex); private void ThrHighlight(object obj) { string[] words = ucSearchControls.rdbExact.Checked ? new string[] { ucSearchControls.txtSearch.Text.Trim() } : ucSearchControls.txtSearch.Text.Split(' '); foreach (string word in words) { int startIndex = 0; while (startIndex < _ucResultRich.rchResult.TextLength) { int wordStartIndex = _ucResultRich.rchResult.Find(word, startIndex, RichTextBoxFinds.None); if (wordStartIndex != -1) { _ucResultRich.rchResult.SelectionStart = wordStartIndex; _ucResultRich.rchResult.SelectionLength = word.Length; _ucResultRich.rchResult.SelectionBackColor = Color.Yellow; } else break; startIndex += wordStartIndex + word.Length; } } } 

我怎样才能做到这一点?

PS:这是我的第一个问题的后续行动以及那里的@varocarbas评论

这个答案专门用于展示如何正确使用(即,通过最大化其内置function) BackgroundWorker (它是我在OP的前一篇文章中写的一些评论的延续)来提供预期的function。

要使用这些行下面的代码,请启动一个新的Winforms项目并将以下控件添加到主窗体: Button (带有单击事件Button button1button1 ), RichTextBoxrichTextBox1 )和BackgroundWorker (带有DoWork事件backgroundWorker1_DoWorkProgressChanged backgroundWorker1_DoWork event backgroundWorker1_ProgressChanged ); 另请注意, Form1_Load是主窗体的Load事件。

要使用该应用程序,只需通过包含一些硬编码的单词(即“word1”,“word2”,“word3”,“word4”,“word5”)输入richTextBox1的任何文本,单击button1并确认它们按预期突出显示。

 volatile int curWordStartIndex; //I use this global variable to communication between the progressChanged event and findBit, called from the DoWork event private void Form1_Load(object sender, EventArgs e) { backgroundWorker1.WorkerReportsProgress = true; } private void button1_Click(object sender, EventArgs e) { //As far as richTextBox1.TextLength provokes a cross-thread error, I pass it as an argument backgroundWorker1.RunWorkerAsync(richTextBox1.TextLength); } private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { findBit((int)e.Argument); } private void findBit(int textLength) { string[] words = new string[] { "word1", "word2", "word3", "word4", "word5" }; foreach (string word in words) { int startIndex = 0; while (startIndex < textLength) { //Rather than performing the actions affecting the GUI thread here, I pass all the variables I need to //the ProgressChanged event through ReportProgress and perform the modifications there. backgroundWorker1.ReportProgress(0, new object[] { word, startIndex, Color.Yellow }); if (curWordStartIndex == -1) break; startIndex += curWordStartIndex + word.Length; } } } private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { object[] curVars = (object[])e.UserState; richTextBox1.SuspendLayout(); string word = (string)curVars[0]; int startIndex = (int)curVars[1]; Color curColor = (Color)curVars[2]; curWordStartIndex = richTextBox1.Find(word, startIndex, RichTextBoxFinds.None); if (curWordStartIndex != -1) { richTextBox1.SelectionStart = curWordStartIndex; richTextBox1.SelectionLength = word.Length; richTextBox1.SelectionBackColor = curColor; } richTextBox1.ResumeLayout(); } 

您需要将代码与UI控件分离,并在外部线程上执行业务逻辑,并在Dispatcher.BeginInvoke或Invoke上更新UI控件。

例如,您可以将文本框中包含的文本保存在单独的属性中,并在完成UI线程上的UI突出显示部分后,在其他线程上执行查找。