使用 Parallel BeginInvoke 有效而 Invoke 无效时 - c# 4.0

发布于 2024-12-07 10:12:57 字数 773 浏览 0 评论 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

極樂鬼 2024-12-14 10:12:57

您的 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 use Invoke if you want, and while it's doing the computation the UI will still be responsive.

尴尬癌患者 2024-12-14 10:12:57

听起来你的 UI 线程陷入了僵局。这是完全有道理的,因为您的 button2_ClickFor 完成之前不会退出,并且特别是,直到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 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).

入画浅相思 2024-12-14 10:12:57

我认为这是因为主线程在上面的 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文