繁体   English   中英

使用Control.Invoke死锁?

[英]Deadlock using Control.Invoke?

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

我不知道为什么该应用程序变得无响应。 我有僵局吗?

MyRepresentation内部,我对OpenGL进行了一些调用。

view是Form1(主窗体)内部的一个控件。

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

在“并行任务”窗口中,我得到以下信息:

ID  Status       Message<br>
1    ?Waiting   Task1 is waiting on object: "Task2"<br>
2    ?Waiting   No waiting information available<br>

在“调用堆栈”窗口中,我得到以下信息:

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

任何帮助将不胜感激。

是的,您遇到了僵局。 Parallel.ForEach()作用是使用一个或多个线程( 包括当前线程Parallel.ForEach()运行迭代,然后阻塞当前线程,直到所有迭代完成为止。

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

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

我不了解代码的确切功能(似乎它覆盖了每次迭代中的representation ),但是我认为您应该从后台线程运行ForEach() 这意味着DoRepresentation()将在完成工作之前返回,因此Invoke()将正常工作。

通常,长时间阻塞UI线程不是一个好主意,因此您应该在另一个线程上运行所有耗时的代码。

您可以使用Invoke方法的BeginInvoke指令。 如果仍然需要,则可以锁定一个对象,并确保在实现之前无法从另一个线程访问该对象。

使用开始调用方法

void UpdateRepresentation(object g)
{
  view.BeginInvoke( new Action(() =>
  {
    representation = new MyRepresentation(g);
  }));
}

使用锁

void UpdateRepresentation(object g)
{
lock(this) 
{
 view.Invoke(new Action(() =>
  {
    representation = new MyRepresentation(g);
  }));
}

}

此注释适用于我的特定应用程序,该应用程序是C#中的Windows应用程序:使用锁也不适合我,该应用程序只是冻结了。 BeginInvoke工作,但是我不喜欢异步更新UI控件的效果。

我最终以一个单独的线程( System.Threading.Tasks.Task )启动主进程,该进程将启动并立即将主线程的控制权交还给我。 然后,在等待其他任务循环结束执行时,我还不得不插入以下行: System.Windows.Forms.Application.DoEvents()以使系统能够处理队列中所有等待的消息。 现在它适合我的应用程序。 可能还有另一种方法可以给这只猫蒙皮,但现在可以用了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM