1

私は構造体を作成し、そのメソッドAStructをオーバーライドしました。ToString()次に、いくつかを返し、AStructそれらをリストに入れるための並列を作成したので、 a を使用し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();

問題は、出力ファイルに AList の 7/8 行しか出力されないのに対し、AList は実際には 10 個の要素すべてを取得していることです。これは StringBuilder のスレッドセーフに関係しているのだろうか。すべての行が出力されない理由を誰かが説明できますか?

4

1 に答える 1

2

上記のコードでは、 のインスタンスは、スレッド (または を作成しているスレッド)StringBuilder以外によってアクセス/変更されることはないため、 のスレッドセーフは関係ありませが、対処するときに常に覚えておくべきはるかに大きなバグがあります。複数のスレッド。mainswStringBuilder

リソースがスレッドセーフでない限り、共有リソースを複数のスレッドで変更しないでください

AListを異なるスレッドから更新しているため、lockアクセスを同期するために a を使用するか、 (順序がConcurrentQueue保証されている) またはConcurrentBag(順序が保証されていない) スレッドセーフなコレクションを使用してください。

また、 10ではなく9エントリを追加しています。AList

最後に、期待される結果をもたらす変更されたコードを次に示します。

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 に答える