当使用并行BeginInvoke时,Invoke正在工作,而Invoke不是-c#4.0

当使用并行BeginInvoke时,Invoke正在工作,而Invoke不是-c#4.0,c#,winforms,invoke,begininvoke,parallel-for,C#,Winforms,Invoke,Begininvoke,Parallel For,如下图所示,当我在AddListBoxItem函数中使用invoke时,软件将变得无响应和冻结,但如果我使用BeginInvoke,它会工作。为什么会这样 visual studio 2010,C#4.0 private void button2_Click(object sender, EventArgs e) { var watch = Stopwatch.StartNew(); Parallel.For(2, 20, (i) => { var

如下图所示,当我在AddListBoxItem函数中使用invoke时,软件将变得无响应和冻结,但如果我使用BeginInvoke,它会工作。为什么会这样

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);
    }
}

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

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

因此,出现了死锁-UI线程正在等待任务,而这些任务正在等待UI线程
BeginInvoke
起作用,因为这样任务线程就不会等待在UI线程中处理委托


我建议您不要在UI线程中首先调用
Parallel.For
。无论如何,在UI完成之前,您将阻止它,这不是一个好主意。在后台线程中完成整个过程-然后,如果需要,您仍然可以使用
调用
,并且当它进行计算时,UI仍然会有响应。

我认为这是因为主线程在上面的单击事件中被阻塞,等待完成AddListBoxItem,这正在等待bution2\u单击事件返回。

您的UI中不应该有控制器逻辑,因此主要的问题是单击没有在不同的线程中回调逻辑

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

听起来您好像在死锁UI线程。这很有道理,因为您的
按钮2\u单击
直到
For
完成后才会退出,特别是在
按钮2\u单击
完成之前,无法处理任何消息循环事件。如果您在另一个线程上,
Invoke
使用一个消息循环事件,并且在处理该项之前不会返回-因此不会执行任何操作-并且对于
/
按钮2\u单击
将永远不会完成


通过使用
BeginInvoke
您只需将此工作排队-
BeginInvoke
立即返回。这意味着
可以完成,它让
按钮2\u单击
完成,然后允许处理消息循环事件(更新UI)。

我如何在不同的线程中调用它?我的意思是调用parallel.for?@MonsterMMORPG:从一个不同的线程以其他线程的方式完成整个任务-从BackgroundWorker,或者使用ThreadPool.QueueUserWorkItem,甚至Task.Factory.StartNew。我认为任务更好谢谢你的回答。现在我明白了为什么变得不响应了:)我认为在任务中删除它最有可能不需要额外的线程。@HenkHolterman:可能与使用ThreadPool.QueueUserWorkItem差不多,但绝对更干净。