【发布时间】:2013-04-05 20:40:26
【问题描述】:
我正在使用 tpl 来并行执行数据。问题是有时它会无缘无故地挂起这样的输出:
The thread '<No Name>' (0x4aa4) has exited with code 0 (0x0).
The thread '<No Name>' (0x2bf4) has exited with code 0 (0x0).
The thread '<No Name>' (0x417c) has exited with code 0 (0x0).
The thread '<No Name>' (0x432c) has exited with code 0 (0x0).
The thread '<No Name>' (0x3ad0) has exited with code 0 (0x0).
The thread '<No Name>' (0x4440) has exited with code 0 (0x0).
The thread '<No Name>' (0x24e8) has exited with code 0 (0x0).
The thread '<No Name>' (0x3354) has exited with code 0 (0x0).
The thread '<No Name>' (0x4a30) has exited with code 0 (0x0).
该程序仍将执行,当我在 Visual Studio 中暂停它时,它会在我有 ForEach 的并行过程的地方暂停:
Parallel.ForEach
(
hold1.remainingHolds.ToArray(),
subSequence =>
{
//only if subsequence has 1 common substring
if (checkIfCommon(remainingSequence, subSequence.ToString()) == 1)
{
goDownLinkType2(subSequence.ToString().Split(','), 0,
(SuffixNode)hold1.childHolds[subSequence.ToString().Split(',')[0]]);
}
}
);
我不认为它是死锁,因为不会有线程等待不同的资源并最终相互锁定
它应该进入这个方法内部并递归遍历一个后缀树,直到它会等到没有线程将任何对象添加到数组列表中
Boolean flag = false;
public void goDownLinkType2
(string[] splittedString,
int index, SuffixNode currentNode)
{
Boolean writingFlag = false;
if (index == 2)
{
while(writingFlag == false)
{
while(flag == true)
{
//blocked
}
if (flag == false)
{
flag = true;
if(!secondChoiceResults.Contains
(currentNode.representingStance.SequenceOfHolds))
{
Console.WriteLine("new addition");
secondChoiceResults.Add
(currentNode.representingStance.SequenceOfHolds,
currentNode.representingStance);
}
flag = false;
writingFlag = true;
}
}
}
else
{
int nextIndex = index + 1;
goDownLinkType2
(splittedString,
nextIndex,
(SuffixNode)currentNode.childHolds[splittedString[nextIndex]]
);
}
}
【问题讨论】:
-
Parallel.ForEach最终会终止吗?如果是这样,这是设计使然。它正在终止线程池中为满足您的请求而旋转的所有线程。如果它没有终止,是否存在使一个或多个线程保持打开状态的边界条件? -
在程序中它应该终止,但在这种情况下它不应该在那个阶段,因为并非所有数据都会被处理。之后它应该到达一个永远不会到达的断点,程序只是挂在 foreach 上。
-
您是否可能将输出解释为处理的终止,而实际上可能只是
Parallel.ForEach不再需要这些线程,因此将它们释放到 ThreadPool ?如果您想要一个更具体的答案,您需要告诉我们更多关于您的断点的信息:它在哪里,那里有什么代码,以及为什么您希望它被命中。 -
如果是这样,可能是 1 个线程卡在 foreach 内的问题?因为所有其他线程都已准备好处理它们并且 1 被卡住了。
-
将 Parallel.ForEach 与 any 共享数据(如
flag、remainingSequence)一起使用通常不是一个好主意。该共享数据由多个线程读取,应该受到保护或通过违规访问来访问...
标签: c# debugging c#-4.0 concurrency task-parallel-library