并行.失败(C#)

ato*_*hod 4 c# parallel-processing

我写了一些代码:

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>(); 
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

但结果不是预期的(

并非所有循环都在Console.WriteLine调用之前完成

使用Parallel.For有什么问题?

Ale*_*ore 7

你正在遇到所谓的竞争条件.由于.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>();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ConcurrentBag是最接近线程安全列表的东西.请记住,因为我们正在处理未知的调度,所以整数将不按顺序排列.