Reputation: 31
How can I do to access an element from another thread? In the case, I have a richtextbox in the Main Thread (GUI), and I'm running a method on a secondary thread. I want to access the richeditbox through the secondary thread
private void Log(string input, Label lbl)
{
lbl.Invoke(new Action(()=>
{
lbl.Text = "Status: " + input;
Thread.Sleep(50);
}));
}
void Run()
{
foreach (string line in richTextBox1.Lines)
{
Log(line, label1);
Thread.Sleep(500);
}
}
private void button1_Click(object sender, EventArgs e)
{
ThreadStart th = new ThreadStart(() => Run());
Thread th2 = new Thread(th);
th2.Start();
//th2.Join();
}
The following error is shown:
Invalid thread operation: control 'richTextBox1' accessed from a thread that is not the one in which it was created.
Upvotes: 1
Views: 387
Reputation: 39122
Here's another version...not that you shouldn't be sleeping in the Log() method as that is running in the UI thread!
private void button1_Click(object sender, EventArgs e)
{
ThreadStart th = new ThreadStart(() => Run());
Thread th2 = new Thread(th);
th2.Start();
}
void Run()
{
string[] lines = (string[])richTextBox1.Invoke(new Func<string[]>(() => richTextBox1.Lines));
foreach (string line in lines)
{
Log(line, label1);
Thread.Sleep(500);
}
}
private void Log(string input, Label lbl)
{
lbl.Invoke(new Action(() =>
{
lbl.Text = "Status: " + input;
}));
}
Upvotes: 0
Reputation: 12811
You're already doing this. Your Log
method shows the correct thing to do -- use Invoke
to run some code on the UI thread. In this case, you could do something like:
void Run()
{
var getLines = new Func<object>(() => richTextBox1.Lines);
var lines = (string[]) richTextBox1.Invoke(getLines);
foreach (var line in lines)
{
Log(line, label1);
Thread.Sleep(500);
}
}
However, this really isn't necessary. It looks like you really want to read the Lines
property once when your button is clicked and just pass it to the background thread.
void Run(string[] lines)
{
foreach (var line in lines)
{
Log(line, label1);
Thread.Sleep(500);
}
}
private void button1_Click(object sender, EventArgs e)
{
var lines = richTextBox1.Lines;
var th = new ThreadStart(() => Run(lines));
var th2 = new Thread(th);
th2.Start();
}
Upvotes: 1