Reputation: 330
When this code runs and all the three threads are running the displaying of the random number in the labels becomes slow. While when stopping one or two threads the processing becomes faster. Why is that?
namespace MultiThreadingCheckBox
{
public partial class Form1 : Form
{
Thread t1, t2, t3;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
t1 = new Thread(new ThreadStart(DoWork1));
t2 = new Thread(new ThreadStart(DoWork2));
t3 = new Thread(new ThreadStart(DoWork3));
t1.Start();
t2.Start();
t3.Start();
}
private void DoWork1()
{
Random p = new Random();
while (true)
{
label1.Invoke(new MethodInvoker(delegate { label1.Text = p.Next(1, 1000).ToString(); }));
}
}
private void DoWork2()
{
Random p = new Random();
while (true)
{
label2.Invoke(new MethodInvoker(delegate { label2.Text = p.Next(1, 1000).ToString(); }));
}
}
private void DoWork3()
{
Random p = new Random();
while (true)
{
label3.Invoke(new MethodInvoker(delegate { label3.Text = p.Next(1, 1000).ToString(); }));
}
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (checkBox1.Checked == true)
{
t1.Suspend();
label1.Invoke(new MethodInvoker(delegate { label1.Text = "I am stopped"; }));
}
else
t1.Resume();
}
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
if (checkBox2.Checked == true)
{
t2.Suspend();
label2.Invoke(new MethodInvoker(delegate { label2.Text = "I am stopped"; }));
}
else
t2.Resume();
}
private void checkBox3_CheckedChanged(object sender, EventArgs e)
{
if (checkBox3.Checked == true)
{
t3.Suspend();
label3.Invoke(new MethodInvoker(delegate { label3.Text = "I am stopped"; }));
}
else
t3.Resume();
}
}
}
Upvotes: 3
Views: 3089
Reputation: 91
As an aside, since Yochai Timmer and dotnetstep have already explained why this is performing slow, I'd also like to suggest using Tasks instead of spawning your own threads. Tasks will manage a thread pool for you and probably do it more efficiently than you can realistically manage without putting too much effort into it.
Obviously, what you've written is an example application though, so you may already know about Tasks. In that case, I agree with Yochai, you should definitely be using BeginInvoke to asynchronously access the UI.
Upvotes: 0
Reputation: 49221
First of all, displaying stuff on a form requires the UI thread to do work.
So, when you do Invoke() you call a synchronous call to the UI thread to change the display.
This means the thread sends a message to the UI thread, and goes to sleep until it was signaled that it finished.
To avoid this, use BeginInvoke
, this will send an asynchronous message to the UI thread, and won't pause the thread.
Now a second issues is that you're using more threads than you have cores.
So the CPU can't really run it in parallel because of actual physical reasons, it doesn't have another core to do it with.
So it's not true parallelism, which in addition to the fact that the threads go to sleep in the Invoke, you get slow performance.
Upvotes: 7
Reputation: 17485
First of all as your all thread process has continues loop each time thread is waiting for execution.
Now second thing comes to System Configuration. If you have multicore system then each core can execute one thread so if 4 core are then then three thread execute parallel but if single core or two core then thread has to wait for execution.
Third point is that each time when you use invoke for label to update each switch context back to UI thread so that also reduce and affect the performance of application.
Upvotes: 5