我建设VS2010旗舰版使用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几个电话。
视图是内部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()
的作用是,它使用一个或多个线程包括当前 ,然后阻止当前线程,直到所有的迭代完成运行迭代。
这意味着,如果你调用DoRepresentation()
从UI线程,你会得到一个僵局:UI线程正在等待其他线程的迭代来完成,而其他线程都在等待Invoke()
来完成,这是不可能发生的如果UI线程被阻塞。
此外,在你的情况下,使用Parallel.ForEach()
没有任何意义(假设这是你的实际代码):在运行new MyRepresentation()
在UI线程上。
我不明白,究竟是什么做的(好像它覆盖的代码representation
在每次迭代中),但我想你应该运行ForEach()
从后台线程。 这意味着DoRepresentation()
将完成其工作,因此之前返回Invoke()
将正常工作。
在一般情况下,它不阻塞很长一段时间的UI线程是一个好主意,所以你应该运行在另一个线程的费时码。
您可以使用调用方法的BeginInvoke的insteed。 如果你还需要,那么你可以锁定对象,并确保直到意识到这将无法访问来自其他线程。
使用开始调用方法
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()
以使系统能够处理在队列中等待的所有消息。 现在,它的工作适合我的申请。 有可能是另一种方法对皮肤这只猫,但现在的工作。