使用 Control.Invoke 死锁? [英] Deadlock using Control.Invoke?

查看:42
本文介绍了使用 Control.Invoke 死锁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 VS2010 Ultimate 中使用 TPL 构建应用程序.大多数情况下,当我从 UI 线程调用 DoRepresentation() 时,我运行该应用程序时它会变得无响应.

void DoRepresentation(){Parallel.ForEach(cgs, loopOptions, g =>{更新表示(g);});}无效更新表示(对象 g){view.Invoke(new Action(() =>{表示 = 新的 MyRepresentation(g);}));}

我不知道为什么该应用没有响应.我是否陷入僵局?

MyRepresentation 内部,我调用了 OpenGL.

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

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

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

ID 状态信息
1 ?Waiting Task1 正在等待对象:Task2"
2 ?Waiting 没有可用的等待信息<br>

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

[在睡眠中,等待或加入]
[外部代码]
Test.dll!Render.DoRepresentation()
App1.exe!Form1.Button1_Click

任何帮助将不胜感激.

解决方案

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

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

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

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

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

I'm building an app using TPL in VS2010 Ultimate. The most of the times I run the app it becomes unresponsive when I Call DoRepresentation() from the UI's thread.

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

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

I don't know why the app is becoming unresponsive. Am I having a deadlock?

Inside MyRepresentation I do some calls to OpenGL.

view is a Control inside Form1 (the main form).

When the app become unresponsive I pause it from the VS IDE and here's the info I get

In the "Parallel Tasks" window I get the following:

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

In the "Call Stack" window I get the following:

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

Any help will be appreciated.

解决方案

Yes, you are having a deadlock. What Parallel.ForEach() does is that it runs the iterations using one or more threads including the current one and then blocks the current thread until all iterations are complete.

This means that if you call DoRepresentation() from the UI thread, you get a deadlock: the UI thread is waiting for iterations on other threads to finish, while those other threads are waiting for Invoke() to finish, which can't happen if the UI thread is blocked.

Also, in your case, using Parallel.ForEach() doesn't make any sense (assuming this is your actual code): you run new MyRepresentation() on the UI thread.

I don't understand what exactly is the code doing (it seems it overwrites representation in each iteration), but I think you should run ForEach() from a background thread. This means DoRepresentation() will return before it finishes its work and so Invoke() will work correctly.

In general, it's not a good idea to block the UI thread for a long time, so you should run any time-consuming code on another thread.

这篇关于使用 Control.Invoke 死锁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆