リストビルダーのメソッドがたくさんの文字列(1百万項目)を含む文字列のIEnumerableを返し、それを文字列のリストに格納した後、すべての項目をParallel.ForeachのStringBuilderインスタンスです。その後、私はstringBuilderInstance.Lengthを印刷しました。ConcurrentBagはスレッドセーフではないようです
問題は1000000未満でした。 の後に、私はリストコレクションがスレッドセーフではないことに気づきました。これがこの問題の原因です。
1)を使用しロック
2)ConcurrentBag
私はロックを使用していた場合、それはOKで、長さは1 milionですが、を使用してください: だから2ソリューションは、私の心を交差します:
文字列のConcurrentBagを使用しているとき、長さが予想よりも短くなっています。
この問題の根本的な原因は何ですか?
リスト・クリエーター方法:
public static void DoWithParallel_ThreadSafe()
{
ConcurrentBag<string> listOfString = new ConcurrentBag<string>(CreateList());
StringBuilder a = new StringBuilder();
Action<string> appender = (number) =>
{
a.Append(number);
};
Parallel.ForEach(listOfString, appender);
Console.WriteLine($"The string builder lenght : {a.Length}");
}
使用してロック:ConcurrentBagを使用して
public static List<string> CreateList()
{
List<string> result = new List<string>();
for (int i = 0; i < 1000000; i++)
{
result.Add(1.ToString());
}
return result;
}
public static void DoWithParallel_UnsafeThread_Lock()
{
List<string> listOfString = CreateList();
StringBuilder a = new StringBuilder();
Action<string> appender = (number) =>
{
lock (listOfString)
{
a.Append(number);
}
};
Parallel.ForEach(listOfString, appender);
Console.WriteLine($"The string builder lenght : {a.Length}");
}
メイン:
static void Main(string[] args)
{
DoWithParallel_UnsafeThread_Lock();
DoWithParallel_ThreadSafe();
Console.ReadKey();
}
ありがとうございます。
スレッドセーフなコードを書く前に、スレッディングについて学ぶ必要があります。 – SLaks
http://blog.slaks.net/2013-07-22/thread-safe-data-structures/ – SLaks
Parallel.ForEachがスレッドセーフな方法で最初の引数に渡すIEnumerableを呼び出すことがわかりましたその引数のために渡していたコレクションは関係ありません。 –