When using Parallel BeginInvoke is working while Invoke is not - c# 4.0
When i use invoke inside AddListBoxItem function as seen below software become unreponsive and frozen but if i use BeginInvoke it works. Why is that happening ?
visual studio 2010 , C# 4.0
private void button2_Click(object sender, EventArgs e)
{
var watch = Stopwatch.StartNew();
Parallel.For(2, 20, (i) =>
{
var result = SumRootN(i);
AddListBoxItem("root " + i + " : " + result);
});
AddListBoxItem(watch.ElapsedMilliseconds.ToString());
}
private delegate void AddListBoxItemDelegate(object item);
private void AddListBoxItem(object item)
{
if (this.listBox1.InvokeRequired)
{
this.listBox1.Invoke(new AddListBoxItemDelegate(this.AddListBoxItem), item);
}
else
{
th开发者_如何学Pythonis.listBox1.Items.Add(item);
}
}
Your UI thread will wait for Parallel.For
to complete before it continues. That means it can't process any further UI messages until it's completed.
Now when the worker threads call Invoke
, they wait until the UI thread processes the delegate before they continue. So they're waiting for the UI thread to get free, basically.
Hence, you have a deadlock - the UI thread is waiting for the tasks, which are waiting for the UI thread... BeginInvoke
works because then the task threads don't wait for the delegates to be processed in the UI thread.
I would suggest that you don't call Parallel.For
in the UI thread to start with. You'll block the UI until it completes anyway, which isn't a good idea. Do the whole thing in a background thread - then you can still use Invoke
if you want, and while it's doing the computation the UI will still be responsive.
It sounds like you are deadlocking the UI thread. This makes perfect sense, as your button2_Click
doesn't exit until For
completes, and in particular, no message-loop events can be processed until button2_Click
has completed. If you are on a different thread, Invoke
uses a message-loop event, and does not return until that item is processed - so nothing will ever be done - and For
/ button2_Click
will never complete.
By using BeginInvoke
you simply queue this work - BeginInvoke
returns immediately. This means that the For
can complete, which lets button2_Click
complete, which then allows the message-loop events to be processed (updating the UI).
I think it's because auf the Mainthread beeing blocked in the above Click event, waiting to finish AddListBoxItem, which is waiting the buttion2_click event to return.
You shouldn't have Controller logic in your UI, so the main problem that the Click isn't calling back a logic in a different thread.
After Implementing an thread for your logic, your GUI wouldn't block and would refresh easy in any situation.
精彩评论