我创建了一个结构,比如AStruct
,并覆盖其ToString()
方法。然后我写了一个并行for来返回一些AStruct
并将它们放在一个列表中,这样我就可以使用StreamWriter
来输出它们,比如
StreamWriter sw = new StreamWriter(@"ABC.txt");
StringBuilder sb = new StringBuilder();
List<AStruct> AList = new List<AStruct>();
Parallel.For(0,10,i => // generate 10 AStruct(s)
{
AList.Add(DoSomethingThatReturnsAStruct);
});
for(int i =0; i< AList.Count();i++) //put in a StringBuilder
{
sb.AppendLine(AList[i].ToString());
}
sw.Write(sb.ToString());
sw.Close();
问题是输出文件只打印7/8行AList,而AList实际上得到了所有10个元素。我想知道这与StringBuilder的线程安全性有关。有人可以解释为什么不输出所有行?
答案 0 :(得分:2)
在上面的代码中,StringBuilder
的实例永远不会被main
线程(或任何创建sw
的线程)以外的任何东西访问/修改,所以StringBuilder
的线程安全性{ {1}}不相关然而你有一个更大的错误,在处理多个帖子时你应该永远记住它。
除非这样,否则永远不要修改多个线程的共享资源 资源是线程安全的
您正在更新来自不同线程的AList
,因此要么使用lock
来同步访问权限,要么使用线程安全的集合,例如ConcurrentQueue
(保证订单)或ConcurrentBag
(订单无保证)
您还要将 9 条目添加到AList
而不是 10 。
最后,这是您修改后的代码,它会产生预期的结果。
var sw = new StreamWriter(@"ABC.txt");
try
{
var AList = new List<AStruct>();
var locker = new object();
Parallel.For(0, 10, i => // generate 10 AStruct(s)
{
lock (locker) { AList.Add(new AStruct()); }
});
var sb = new StringBuilder();
for (int i = 0; i < AList.Count; i++) //put in a StringBuilder
{
sb.AppendLine(AList[i].ToString());
}
sw.Write(sb.ToString());
} finally
{
sw.Close();
}