如何使用ImmutableList<>而是List<>获得线程安全?

时间:2016-03-04 14:26:46

标签: c# multithreading thread-safety immutablelist

例如我有这段代码:

 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Collections.Immutable;
 using System.Linq;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;

 namespace ConsoleApplication2
{
class Program
{
    static void Main(string[] args)
    {
        var lst =new List<int>();
        for (int i = 0; i < 2000000; i++)
        {
            lst.Add(i);
        }

        new Thread(() =>
        {                
            for (int i = 20000001; i < 21000000; i++)
            {
                lst.Add(i);
            }

        }).Start();
        new Thread(() =>
        {
            lst.Where(item =>
                  item > 85200 && item < (50000 * (item + 154896556) * 2 / 1000)
              ).ToList();

        }).Start();

        new Thread(() =>
       {
           for (int i = 21000001; i < 22000000; i++)
           {
               lst.Add(i);
           }

       }).Start();
    }
}
}

我得到了这个异常(附加信息:集合被修改;枚举操作可能无法执行。)因为我在一个线程中进行了更改并在另一个线程中进行迭代。 这是我的问题:如何通过System.Collections.Immutable.ImmutableList&lt;&gt;重写此代码而不是List&lt;&gt;?

2 个答案:

答案 0 :(得分:2)

为了获得线程安全性,您可以使用许多线程安全的集合:

  • BlockingCollection
  • ConcurrentDictionary
  • ConcurrentQueue
  • ConcurrentStack
  • ConcurrentBag

您甚至可以使用IProducerConsumerCollection实现自己的

所有记录在这里: https://msdn.microsoft.com/en-us/library/dd997305(v=vs.110).aspx

答案 1 :(得分:0)

您确定要一个ImmutableList&lt;&gt ;?引用文档:

  

当您从不可变列表中添加或删除项目时,原始列表的副本是在添加或删除项目的情况下创建的,原始列表不会更改。

     

...

     

它返回一个添加了对象的新的不可变列表,如果它已经包含指定的对象,则返回当前列表。

尝试在lock(list){}块中包装编辑列表的任何实例,例如:

lock(lst) 
{   
  list.Add(i);
}

当您的代码尝试从List&lt;&gt;中读取时,您会遇到(可能非常轻微)性能损失但它已被锁定以进行编辑,但它应该是线程安全的。