3

当我在 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);
    }
}
4

3 回答 3

3

您的 UI 线程将等待Parallel.For完成,然后再继续。这意味着它在完成之前无法处理任何进一步的 UI 消息。

现在,当工作线程调用 时Invoke,它们会等到 UI 线程处理委托后再继续。所以他们基本上在等待 UI 线程释放。

因此,您遇到了死锁 - UI 线程正在等待正在等待 UI 线程BeginInvoke的任务......因为任务线程不会等待在 UI 线程中处理委托。

我建议你不要Parallel.For在 UI 线程中调用。无论如何,您都会阻止 UI 直到它完成,这不是一个好主意。在后台线程中完成所有操作 -Invoke如果需要,您仍然可以使用,并且在它进行计算时,UI 仍然会响应。

于 2011-10-02T19:58:27.337 回答
3

听起来你正在死锁 UI 线程。这是非常有意义的,因为您在完成button2_Click之前不会退出,特别是在完成之前不能处理任何消息循环事件。如果您在不同的线程上,使用消息循环事件,并且在处理该项目之前不会返回 - 所以什么都不会做 - 并且/永远不会完成。Forbutton2_ClickInvoke Forbutton2_Click

通过使用BeginInvoke,您只需将这项工作排队BeginInvoke-立即返回。这意味着For可以完成,让button2_Click完成,然后允许处理消息循环事件(更新 UI)。

于 2011-10-02T20:01:59.097 回答
1

我认为这是因为在上面的 Click 事件中阻塞了 Mainthread,等待完成 AddListBoxItem,它正在等待 button2_click 事件返回。
您的 UI 中不应该有 Controller 逻辑,因此 Click 的主要问题不是回调不同线程中的逻辑。

在为您的逻辑实现线程后,您的 GUI 不会阻塞并且在任何情况下都可以轻松刷新。

于 2011-10-02T20:01:56.843 回答