C# 并行StringBuilder的线程安全性。用于
我已经创建了一个结构,比如说C# 并行StringBuilder的线程安全性。用于,c#,parallel-for,C#,Parallel For,我已经创建了一个结构,比如说AStruct,并重写了它的ToString()方法。然后我编写了一个并行程序,用于返回一些AStruct,并将它们放在一个列表中,这样我就可以使用StreamWriter输出它们,如 StreamWriter sw = new StreamWriter(@"ABC.txt"); StringBuilder sb = new StringBuilder(); List<AStruct> AList = new List<AStruct>();
AStruct
,并重写了它的ToString()
方法。然后我编写了一个并行程序,用于返回一些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();
StreamWriter sw=新的StreamWriter(@“ABC.txt”);
StringBuilder sb=新的StringBuilder();
列表列表=新列表();
Parallel.For(0,10,i=>//生成10个AStruct
{
列表。添加(返回结构的dosomething);
});
对于(int i=0;i
问题是输出文件只打印7/8行列表,而列表实际上得到了所有10个元素。我想知道这是否与StringBuilder的线程安全有关。有人能解释为什么不输出所有行吗?在上面的代码中,
StringBuilder
的实例从来不会被主线程以外的任何线程(或创建sw
的任何线程)访问/修改因此StringBuilder
的线程安全性是不相关的,但是您有一个更大的bug,在处理多个线程时,您应该始终记住这个bug
永远不要通过多个线程修改共享资源,除非
资源是线程安全的
您正在从不同的线程更新列表
,因此可以使用锁
同步访问或线程安全集合,例如ConcurrentQueue
(订单保证)或ConcurrentBag
(订单不保证)
您还在列表中添加了9个条目,而不是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();
}
var sw=newstreamwriter(@“ABC.txt”);
尝试
{
var AList=新列表();
var locker=新对象();
Parallel.For(0,10,i=>//生成10个AStruct
{
锁(锁){AList.Add(new AStruct());}
});
var sb=新的StringBuilder();
for(inti=0;i
这里的问题不是Stringbuilder,而是并行操作的List
。@IanMercer不,不是,请再次阅读他的问题,尤其是最后一段。而AList实际上得到了所有10个元素。@kchpchan 1,10并行。对于生成9个元素,而不是10个,执行0,10或1,11@CSharpie-可能是在逐步调试时。对于Add
,列表不是线程安全的。首先解决这个问题。代码是否被try-catch包围?捕获一般异常或ArgumentOutOfRange
异常?在这里使用锁将使并行。For
毫无意义。并发集合实际上对我很有用。谢谢