Reputation: 794
Greetings, I'm having problem invoking a richTextBox from a worker thread in C#. I'm using the InvokeRequired/Invoke method. Please see my code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void ThreadSafe(MethodInvoker method)
{
if (InvokeRequired)
Invoke(method);
else
method();
}
private void WorkerThread(object data)
{
string msg = "\nhello, i am thread " + data.ToString();
ThreadSafe(delegate
{
richTextBox1.AppendText(msg);
});
}
private void button1_Click(object sender, EventArgs e)
{
Thread[] workers = new Thread[3];
for (int i = 0; i < 3; i++)
{
workers[i] = new Thread(WorkerThread);
workers[i].Start(i);
string msg = "\nthread " + i.ToString() + "started!";
richTextBox1.AppendText(msg);
}
int j = 3;
while (j > 0)
{
for (int i = 0; i < 3; i++)
{
Thread.Sleep(250);
richTextBox1.AppendText("\nChecking thread");
if (workers[i].Join(250))
{
string msg = "\nWorker thread " + i.ToString() + " finished.";
richTextBox1.AppendText(msg);
workers[i] = null;
j--; // decrement the thread watch count
}
}
}
}
}
It prints the following in the rich text box:
thread 0started!
thread 1started!
thread 2started!
Checking thread
Checking thread
Checking thread
Checking thread
....
It goes on and on, the "hello" message doesn't get printed, and the UI is frozen. Then I changed Invoke() to BeginInvoke(), which I know I shouldn't do, then the result is like this:
thread 0started!
thread 1started!
thread 2started!
Checking thread
Worker thread 0 finished.
Checking thread
Worker thread 1 finished.
Checking thread
Worker thread 2 finished.
hello, i am thread 0
hello, i am thread 1
hello, i am thread 2
What is the reason and what do I do?
Thanks in advance.
Upvotes: 1
Views: 2801
Reputation: 631
You are waiting for the worker threads to complete before leaving your button1_Click
method. This is a problem because your threads can't complete until they are able to run the delegate that calls the AppendText
method on that same thread.
When you change to BeginInvoke
you don't have this problem any more because your worker threads don't block waiting on the delegate that calls the AppendText
method.
If you are trying to block the UI thread until the worker threads complete you simply will not be able to as long as they rely on the call to Invoke
.
Upvotes: 1
Reputation: 887797
The Invoke
method runs your delegate synchronously—it waits until the UI thread actually runs it before returning control to the caller.
Since the UI thread is waiting for your threads to finish, you get a deadlock.
By contrast, the BeginInvoke
method runs your delegate asynchronously—it returns immediately, and the delegate only runs some time later, when the UI thread is free.
Upvotes: 5
Reputation: 35235
You can't update UI controls from another thread, here is the answer
Upvotes: -1