Mine_Stone
Mine_Stone

Reputation: 189

Access "RichTextBox" Component from another thread

I have a console application, that launches a form application (from another class) in a different thread.

But then, I want to access the richTextBox1 component from my main class, in the main thread and that throws an error which says that I'm trying to access the component from another thread.

My code: (Form application)

public partial class ChatGui : Form
{
    public static RichTextBox textBox;
    public ChatGui()
    {
        InitializeComponent();
        richTextBox1.ReadOnly = true;
        richTextBox1.BackColor = SystemColors.Window;
    }

    public void WriteLine(string line)
    {
        richTextBox1.Text += line+"\r\n";
    }

    private void textBox1_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            WriteLine("[You]: "+textBox1.Text);
            NetworkManager.SendPacket("rchat_msg " + textBox1.Text.Replace(" ", "%20"));
            textBox1.Text = "";
            e.Handled = true;
        }
    }

    public void Exit()
    {
        Application.Exit();
    }

    private void ChatGui_FormClosing(object sender, FormClosingEventArgs e)
    {
        e.Cancel = true;
    }

}

The main console application

public static void StartRemoteChat()
    {
        RemoteChat = true;
        Program.ChatGui = new ChatGui();
        new Thread(new ThreadStart(() =>
        {
            Application.Run(Program.ChatGui);
            while (RemoteChat)
            {
                // ...
            }
        })).Start();
    }

So, how can I access the richTextBox1 component from my main thread (I want to change some variables of the component) without this error happening?

Upvotes: 1

Views: 3369

Answers (4)

Niklas
Niklas

Reputation: 1000

The control is owned by the thread that creates it. In your case the thread that you start owns the form because it paints it so its going to be your forms ui thread.

However when you try to use another thread to make changes to the control, it will throw an exception just like you said. The way around this is to invoke the thread that created it to come and make the change that you want like this:

richTextBox1.BeginInvoke(new Action(()=>
{
// make changes to control here.
}));

i would also suggest you give this a read as i see people suggesting Invoke vs BeginInvoke in Winforms Apps on controls

in short summary :

For Windows Forms apps, I would suggest that you should usually use BeginInvoke. That way you don't need to worry about deadlock

Upvotes: 4

Cody J. Mathis
Cody J. Mathis

Reputation: 652

Simple call invoke to invoke the method from a new thread:

if (InvokeRequired)
{
     Invoke(new Action(**METHODHERE**));
     return;
}

and to pass parameters:

if (InvokeRequired)
{
     Invoke(new Action<string>(**METHODHERE**) **parameter**);
     return;
}

Good read: https://msdn.microsoft.com/en-us/library/ms171728(v=vs.110).aspx

Upvotes: 0

mnaro
mnaro

Reputation: 1

one that can help you is the "CheckForIllegalCrossThreadCalls = false;" but used here(at the beginning):

public Form1()
    {
        InitializeComponent();
        CheckForIllegalCrossThreadCalls = false;            
    }

the advice is to use each call to "RichTextBox1" the invoke method. this method allows to interact with elements created by other threads. example:

richTextBox1.Invoke(new Action(() => richTextBox1.Text = "hello word"));

"CheckForIllegalCrossThreadCalls = false" is a solution that has enough dangers if it is used in complex programs. I hope I was helpful.

Upvotes: 0

mayurb
mayurb

Reputation: 47

try setting following property.

RichTextBox.CheckForIllegalCrossThreadCalls=false;

this may help you.

Upvotes: -2

Related Questions