使用Control.Invoke死锁?

Mic*_*lle 1 c# winforms task-parallel-library

我正在使用VS2010 Ultimate中的TPL构建应用程序.在我运行应用程序的大多数时候,当我从UI的线程调用DoRepresentation()时,它变得没有响应.

void DoRepresentation()
{
  Parallel.ForEach(cgs, loopOptions, g =>
  {
    UpdateRepresentation(g);
  });
}

void UpdateRepresentation(object g)
{
  view.Invoke(new Action(() =>
  {
    representation = new MyRepresentation(g);
  }));
}
Run Code Online (Sandbox Code Playgroud)

我不知道为什么应用程序变得反应迟钝.我有僵局吗?

在MyRepresentation中,我做了一些OpenGL调用.

view是Form1中的一个Control(主窗体).

当应用程序无响应时,我从VS IDE暂停它,这是我得到的信息

在"并行任务"窗口中,我得到以下内容:

ID  Status       Message<br>
1    ?Waiting   Task1 is waiting on object: "Task2"<br>
2    ?Waiting   No waiting information available<br>
Run Code Online (Sandbox Code Playgroud)

在"调用堆栈"窗口中,我得到以下内容:

[In a Sleep, wait, or join]<br>
[External Code]<br>
Test.dll!Render.DoRepresentation()<br>
App1.exe!Form1.Button1_Click<br>
Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激.

svi*_*ick 7

是的,你遇到了僵局.是什么Parallel.ForEach()做的是,它使用一个或多个线程运行的迭代包括当前,然后阻止当前线程,直到所有的迭代完成.

这意味着如果DoRepresentation()从UI线程调用,则会出现死锁:UI线程正在等待其他线程上的迭代完成,而其他线程正在等待Invoke()完成,如果UI线程被阻塞,则不会发生这种情况.

此外,在您的情况下,使用Parallel.ForEach()没有任何意义(假设这是您的实际代码):您new MyRepresentation()在UI线程上运行.

我不明白代码究竟在做什么(似乎它representation在每次迭代中都会覆盖),但我认为你应该ForEach()从后台线程运行.这意味着DoRepresentation()它将在完成其工作之前返回,因此Invoke()将正常工作.

一般来说,长时间阻止UI线程并不是一个好主意,所以你应该在另一个线程上运行任何耗时的代码.