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
毫无意义。并发集合实际上对我很有用。谢谢