gpt4 book ai didi

c# - 并行树打印方法中的错误

转载 作者:太空宇宙 更新时间:2023-11-03 18:41:02 24 4
gpt4 key购买 nike

类:

public class Tree
{
public Node RootNode { get; set; }
}

public class Node
{
public int Key { get; set; }
public object Value { get; set; }
public Node ParentNode { get; set; }
public List<Node> Nodes { get; set; }
}

方法:

此方法生成一棵树。

private static int totalNodes = 0;
static Tree GenerateTree()
{
Tree t = new Tree();
t.RootNode = new Node();
t.RootNode.Key = 0;
t.RootNode.Nodes = new List<Node>();
Console.WriteLine(t.RootNode.Key);
List<Node> rootNodes = new List<Node>();
rootNodes.Add(t.RootNode);
while (totalNodes <= 100000)
{
List<Node> newRootNodes = new List<Node>();
foreach (var rootNode in rootNodes)
{

for (int j = 0; j < 3; j++)
{
totalNodes++;
Console.Write(string.Format(" {0}({1}) ", totalNodes, rootNode.Key));
Node childNode = new Node() {Key = totalNodes, Nodes = new List<Node>(), ParentNode = t.RootNode};
rootNode.Nodes.Add(childNode);
newRootNodes.Add(childNode);
}
Console.Write(" ");
}
Console.WriteLine();
rootNodes = newRootNodes;
}

return t;
}

此方法应该打印一棵树,但在某些情况下节点为空:

 static void PrintTreeParallel(Node rootNode)
{
List<Node> rootNodes = new List<Node>();
List<Node> newRootNodes = new List<Node>();

rootNodes.Add(rootNode);
Console.WriteLine(rootNode.Key);

while (rootNodes.Count > 0)
{
newRootNodes = new List<Node>();
Parallel.ForEach(rootNodes, node =>
{
if (node != null)
{

Console.Write(string.Format(" {0} ", node.Key));
if (node.Nodes != null)
Parallel.ForEach(node.Nodes,
newRoot => { newRootNodes.Add(newRoot); });

}
else
{
//HOW CAN WE GET HERE?????
Debugger.Break();
Console.WriteLine(rootNodes.Count);
}
});

Console.WriteLine();
rootNodes = newRootNodes;
}
}

执行:

 static void Main(string[] args)
{

var t = GenerateTree();
Console.WriteLine("Tree generated");



PrintTreeParallel(t.RootNode);
Console.WriteLine("Tree printed paral");


Console.ReadLine();
}

问题:

这里出了什么问题?为什么节点在某些情况下为空?而且只有当有很多生成的节点时才会发生。例如,如果只有 10 个节点,则一切正常。

最佳答案

问题是你有这段代码:

Parallel.ForEach(node.Nodes, newRoot => { newRootNodes.Add(newRoot); });

这允许多个线程将项目添加到 newRootNodes同时列出。正如评论者指出的那样,List<T>不是线程安全的。可能发生的是一个线程的 Add被另一个线程对 Add 的调用中断,这会导致列表中的内部索引增加。剩下一个 null列表项之一的值。

然后,在循环的后面你有:

rootNodes = newRootNodes; 

这会将损坏的列表作为将要迭代的列表。

关于c# - 并行树打印方法中的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8910339/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com