我写了一些代码:
class Program
{
public const int count = 3000;
static List<int> list = new List<int>();
static void DoWork(int i)
{
list.Add(i);
}
static void Main(string[] args)
{
while (true)
{
Stopwatch s = new Stopwatch();
s.Start();
Parallel.For(0, count + 1, DoWork);
s.Stop();
Console.WriteLine("\n Elapsed: " + s.Elapsed.ToString());
Console.WriteLine("Expected: {0}", count + 1);
Console.WriteLine("count: {0}", list.Count);
Console.ReadKey();
list = new List<int>();
}
}
}
但不期望结果(
在Console.WriteLine调用
之前,并非所有周期都已完成使用Parallel.For有什么问题?
答案 0 :(得分:7)
你正在遇到所谓的Race Condition。由于.Net中的List集合不是线程安全的,因此Add()
之类的操作不是原子的。基本上,在一个线程上调用Add()可以在完成之前销毁另一个线程的Add()。您的代码需要一个线程安全的并发集合。
试试这个:
using System.Threading.Tasks;
class Program
{
public const int count = 3000;
static ConcurrentBag<int> bag = new ConcurrentBag<int>();
static void DoWork(int i)
{
bag.Add(i);
}
static void Main(string[] args)
{
while (true)
{
Stopwatch s = new Stopwatch();
s.Start();
Parallel.For(0, count + 1, DoWork);
s.Stop();
Console.WriteLine("\n Elapsed: " + s.Elapsed.ToString());
Console.WriteLine("Expected: {0}", count + 1);
Console.WriteLine("count: {0}", bag.Count);
Console.ReadKey();
bag = new ConcurrentBag<int>();
}
}
}
ConcurrentBag是最接近线程安全列表的东西。请记住,因为我们正在处理未知的调度,所以整数将不按顺序排列。
答案 1 :(得分:1)
List<>
类不是线程保存。您无法在并行循环中修改它(没有问题)。使用System.Collections.Concurrent
命名空间
答案 2 :(得分:1)