如何从另一个线程调用控制方法 [英] How to call a control method from another thread

查看:116
本文介绍了如何从另一个线程调用控制方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I want to call RichTextBox.Find() from another thread. How can I do that? The RichTextBox is located in a UserControl which I'm using in my form. I want to update it from another thread. I was able to change its properties using Invoke. But can't figure out how to call _ucResultRich.rchResult.Find(word, startIndex, RichTextBoxFinds.None); from my thread.

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评论

P.S: This is the follow-up to my first question and to the @varocarbas comments there

推荐答案

此答案专门用于说明如何正确使用(即,通过最大限度地利用其内置功能)BackgroundWorker(这是对某些产品的延续).我在 OP先前的帖子中写的评论)以提供预期的功能.

This answer is exclusively focused on showing how to use properly (i.e., by maximising its in-built functionalities) BackgroundWorker (it is the continuation of some of the comments I wrote in a previous post of the OP) to deliver the intended functionalities.

要使用这些行下面的代码,请启动一个新的Winforms项目,并将以下控件添加到主窗体中:Button(带有单击事件button1button1),RichTextBox(richTextBox1)和BackgroundWorker(具有DoWork事件backgroundWorker1_DoWorkProgressChanged事件backgroundWorker1_ProgressChangedbackgroundWorker1);还应注意Form1_Load是主窗体的Load事件.

To use the code below these lines, start a new Winforms project and add the following controls to the main form: Button (button1 with the click event button1), RichTextBox (richTextBox1) and a BackgroundWorker (backgroundWorker1 with the DoWork event backgroundWorker1_DoWork and the ProgressChanged event backgroundWorker1_ProgressChanged); also note that Form1_Load is the Load event of the main form.

要使用该应用程序,只需在richTextBox1中输入任何文本即可,包括一些硬编码的单词(即"word1","word2","word3","word4","word5"),然后单击button1并确认它们已按预期突出显示.

To use the application, just input any text in the richTextBox1 by including some of the hardcoded words (i.e., "word1", "word2", "word3", "word4", "word5"), click on button1 and confirm that they are highlighted as expected.

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();
}

这篇关于如何从另一个线程调用控制方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆