Can ToArray() throw an exception?

前端 未结 5 1535
不知归路
不知归路 2020-12-31 13:54

While the answer to this question is excellent, it implies that you should surround calls to List.ToArray() in a lock for concurrency. this blog post also implies that it c

5条回答
  •  暖寄归人
    2020-12-31 14:02

    ToArray is NOT threadsafe, and this code proves it!

    Consider this rather ridiculous code:

            List l = new List();
    
            for (int i = 1; i < 100; i++)
            {
                l.Add(i);
                l.Add(i * 2);
                l.Add(i * i);
            }
    
            Thread th = new Thread(new ThreadStart(() =>
            {
                int t=0;
                while (true)
                {
                    //Thread.Sleep(200);
    
                    switch (t)
                    {
                        case 0:
                            l.Add(t);
                            t = 1;
                            break;
                        case 1:
                            l.RemoveAt(t);
                            t = 0;
                            break;
                    }
                }
            }));
    
            th.Start();
    
            try
            {
                while (true)
                {
                    Array ai = l.ToArray();
    
                    //foreach (object o in ai)
                    //{
                    //    String str = o.ToString();
                    //}
                }
            }
            catch (System.Exception ex)
            {
                String str = ex.ToString();                 
            }
    
        }
    

    This code will fail in a very short run, because of the l.Add(t) line. Because the ToArray is NOT threadsafe, it will allocate the array to the current size of l, then we will add an element to l (in the other thread), and then it will try to copy the current size of l to ai and fail because l has too many elements. ToArray throws an ArgumentException.

提交回复
热议问题