Reputation: 189
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
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
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
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
Reputation: 47
try setting following property.
RichTextBox.CheckForIllegalCrossThreadCalls=false;
this may help you.
Upvotes: -2