使用 Parallel BeginInvoke 有效而 Invoke 无效时 - c# 4.0
当我在 AddListBoxItem 函数中使用调用时,如下所示,软件变得无响应并冻结,但如果我使用 BeginInvoke 它可以工作。为什么会这样?
视觉工作室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
{
this.listBox1.Items.Add(item);
}
}
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
{
this.listBox1.Items.Add(item);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的 UI 线程将等待 Parallel.For 完成后再继续。这意味着在完成之前它无法处理任何进一步的 UI 消息。
现在,当工作线程调用
Invoke
时,它们会等到 UI 线程处理委托后才继续。所以他们基本上是在等待 UI 线程释放。因此,您遇到了死锁 - UI 线程正在等待任务,而任务正在等待 UI 线程...
BeginInvoke
有效,因为任务线程不等待 UI 线程中处理委托。我建议您不要在 UI 线程中调用
Parallel.For
来开始。无论如何,您都会阻止 UI 直到它完成,这不是一个好主意。在后台线程中完成整个操作 - 然后您仍然可以根据需要使用Invoke
,并且在执行计算时 UI 仍将响应。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 useInvoke
if you want, and while it's doing the computation the UI will still be responsive.听起来你的 UI 线程陷入了僵局。这是完全有道理的,因为您的
button2_Click
在For
完成之前不会退出,并且特别是,直到button2_Click
已完成。如果您位于不同的线程上,Invoke
使用消息循环事件,并且在处理该项目之前不会返回 - 因此不会执行任何操作 - 并且For
/button2_Click
永远不会完成。通过使用
BeginInvoke
,您只需排队这项工作 -BeginInvoke
立即返回。这意味着For
可以完成,这让button2_Click
完成,then 允许处理消息循环事件(更新 UI) 。It sounds like you are deadlocking the UI thread. This makes perfect sense, as your
button2_Click
doesn't exit untilFor
completes, and in particular, no message-loop events can be processed untilbutton2_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 - andFor
/button2_Click
will never complete.By using
BeginInvoke
you simply queue this work -BeginInvoke
returns immediately. This means that theFor
can complete, which letsbutton2_Click
complete, which then allows the message-loop events to be processed (updating the UI).我认为这是因为主线程在上面的 Click 事件中被阻塞,等待完成 AddListBoxItem,而 AddListBoxItem 正在等待 buttion2_click 事件返回。
您的 UI 中不应该有控制器逻辑,因此主要问题是 Click 不会回调不同线程中的逻辑。
为您的逻辑实现线程后,您的 GUI 不会阻塞,并且在任何情况下都可以轻松刷新。
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.