1

我创建了一个结构,比如说AStruct,并覆盖它的ToString()方法。然后我写了一个并行返回一些AStruct并将它们放在一个列表中,这样我就可以使用 aStreamWriter来输出它们,比如

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();

问题是输出文件只打印了 AList 的 7/8 行,而 AList 实际上得到了所有 10 个元素。我想知道这是否与 StringBuilder 的线程安全有关。有人可以解释为什么不是所有的行都输出吗?

4

1 回答 1

2

在您上面的代码中,实例永远不会被线程(或正在创建的任何线程)StringBuilder以外的任何东西访问/修改,因此线程安全性无关紧要,但是您有一个更大的错误,您应该在处理时始终记住不止一个线程。mainswStringBuilder

永远不要通过多个线程修改共享资源,除非该资源是线程安全的

您正在AList从不同的线程更新,因此要么使用 alock来同步访问或线程安全的集合,例如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();
}
于 2016-01-24T17:29:05.477 回答