集合类的需求总是源源不断,因此,不管是1.0到2.0的泛型,还是3.0到4.0的并行(本文的并行指Concurrent,非 Parallel),.NET每个版本总会伴随着一些集合类的增长。由于并行计算现在已经越来越流行,这里我将对.NET 4.0中新增的命名空间System.Collections.Concurrent和它下面的类做一些简单的介绍。

  为什么需要Concurrent?

  相信不少朋友都有多线程编程的经历吧,不过在.NET 4.0以前,多线程编程下很容易出问题,先看个简单的例子吧。

static void main()
{
  myList = new List<string>();
  for (int i = 0; i < 1000; i++)
  {
    myList.Add(i.ToString());
  }
  new Thread(T2).Start();
  new Thread(T3).Start();
}
static IList<string> myList;
static void T2()
{
  Thread.Sleep(100);
  for (int i = 0; i < 50; i++)
  {
    myList.Remove(i.ToString());
  }
}
static void T3()
{
  foreach (var a in myList)
  {
    Console.WriteLine(a);
  }
}

  在这个例子中,我们首先初始化一个长度为1000数组,然后我们开启两个线程,一个进行删除操作,另外个则进行简单的读操作。运行代码的话你会发现程序会抛出InvalidOperationException,因为系统集合在被读的同时被修改了,因此列举操作可能不能执行。

  当然在4.0以前我们也有办法避免这种类似的操作,比如我们可以对要操作的对象加锁。即我们可以在对myList集合进行读写操作之前对其添加代码lock (myList)。

然而这种方式毕竟不够简洁,并且在更复杂的情况下它可能会显得非常繁琐。这时候支持并行操作的集合应运而生了。

  有哪些Concurrent集合?

  在System.Collections.Concurrent公开的类并不多,他们分别在两个不同的dll中存在,其中在System.dll中仅仅一个BlockingCollection<T>和ConcurrentBag<T>,在mscorlib.dll中则稍多一些,他们分别是ConcurrentQueue<T>, ConcurrentStack<T>, ConcurrentDictionary<TKey, TValue>。不过对于日常开发来说,他们基本够用。下面我们来一个个看下这些类的构造吧。

  首先看看mscorlib中的几个类,这些类其实我们在.NET 2.0中已经接触过它们的普通版本,因此它们功能基本不变,因此你仍然可以像以前那样使用普通版本的哈希表,队列和堆栈来使用它们。

  不过并行类不仅仅简单以前的集合类改造成线程安全的并行类,它同时还提供了一些更丰富的功能,由于Lamda表达式的引入,现在在 ConcurrentDictionary<TKey, TValue>你可以通过AddOrUpdate或GetOrAdd添加自己的值生成方案。这使得我们在生成键值对的时候更加方便和简单了。如:

ConcurrentDictionary<int, string> td = new ConcurrentDictionary<int, string>();
Func<int, string> genVar = (i) => i.ToString();
Task.Factory.StartNew(() =>
{
  for (int i = 0; i < 1000; i++)
  {
    td.GetOrAdd(i, genVar);
  }
});
Task.Factory.StartNew(() =>
{
  Func<int, string, string> updateVar = (key, oldVar) => oldVar + key;
  td.AddOrUpdate(0, genVar, updateVar);
  Console.WriteLine(td[0]);
}).Wait(); 

我们可以看到,现在我们在取值的时候,如果哈希表中没有该值的话我们可以自己生成,或者我们在添加新的值的时候如果碰到重复键值的时候也可以很方便的解决掉了。相对以前在添加或者查找数据时痛苦的判断,这种方式更加简洁和方便。

  其他几个类相对来说函数使用变化不大,唯一区别比较大的也是在Concurrent命名空间中很常见的各种try函数操作。

  接着我们来看看在System.dll中的并行集合,这里面的两个类在以前的.NET中是没有的。首先看看 ConcurrentBag<T>,顾名思义,这个类提供并行数据包的功能,这个类相对来说构造比较简单,它继承自四个接口:IProducerConsumerCollection<T>, IEnumerable<T>, ICollection, IEnumerable,后面三个集合类常用的接口我们当然很熟悉,而且由于实现了IEnumerable<T>接口,ConcurrentBag<T>也支持LINQ操作。不过这里有个特殊的接口 IProducerConsumerCollection<T>我们以前没有见过,虽然是个新的接口,但故名思意,这个接口提供了生产者/消费者的集合操作,它提供了四个基本的方法:CopyTo(T[],int), ToArray(), TryAdd(T), TryTake(out T)。其中我们主要关注后面的两个方法,TryAdd是添加元素操作,而TryTake则是取元素操作。不过在ConcurrentBag 中,TryAdd方法被设置为protected,外部对象需要通过Add操作来添加元素。另外,取元素的话,除了TryTake之外,我们还可以通过 TryPeek来取集合当前的最后一个元素而不删除它。下面来看看例子:

static void main()
{
  ConcurrentBag<string> bag = new ConcurrentBag<string>();
  Task.Factory.StartNew(() =>
  {
    for (int i = 0; i < 1000; i++)
    {
      bag.Add(i.ToString());
    }
    bag.Add("Last");
  });
  Task.Factory.StartNew(() =>
  {
    foreach (string item in bag)
    {
      Console.WriteLine(item);
    }
  }).Wait();
} 

  BlockingCollection<T>相对来说,要稍微复杂一些,它实现了四个接口:IEnumerable<T>, ICollection, IEnumerable, IDisposable,因此该集合同样支持LINQ,不仅如此,它也提供了比ConcurrentBag更加丰富的功能。如 CompleteAdding和超时设置的TryAdd和TryTake方法等等。

  总结

  随着多线程和并行编程的要求越来越多,相信在未来,.NET家族新增的这些类将会在我们的日常编程生活中越来越常见,所以掌握它们也显得越来越又必要了。

.NET 4.0新增命名空间:System.Collections.Concurrent相关推荐

  1. .Net Framework System.Collections 集合类

    本文内容 集合类 性能 最近复习了一下集合,C# 关于集合的类蛮多,但我除了 List 那几个经常用之外,其他的用得还真不多(只在小范围使用),但其实,每个集合类都各有自己适用的场景,功能也很强大.尤 ...

  2. C# 4.0 新增特性

    之前的文章中,我们曾介绍过C#的历史及C# 4.0新增特性,包括:dynamic. 命名和可选参数.动态导入以及协变和逆变等.今天我们结合代码实例来具体看一下C#4.0中的四个比较重要的特性. 1.d ...

  3. error CS0234: 命名空间“System.Drawing”中不存在类型或命名空间名称“Image”

    c#开发时报错: error CS0234: 命名空间"System.Drawing"中不存在类型或命名空间名称"Image" 右键项目,有个引用,添加引用,弹 ...

  4. 类型实现《程序员的第一年》--------------C#中System.Collections.Generic.SortedDictionary 的使用...

    在改章节中,我们主要介绍类型实现的内容,自我感觉有个不错的建议和大家分享下 SortedDictionary<TKey,TValue> 类型参数 TKey 字典中的键的类型. TValue ...

  5. 使用ILSpy探索C#7.0新增功能点

    第一部分: C#是一种通用的,类型安全的,面向对象的编程语言.有如下特点: (1)面向对象:c# 是面向对象的范例的一个丰富实现, 它包括封装.继承和多态性.C#面向对象的行为包括: 统一的类型系统 ...

  6. 必须进行支持的游戏方可使用此功能_C#8.0 新增功能

    (给DotNet加星标,提升.Net技能) 转自:张传宁cnblogs.com/SavionZhang/p/11201818.html C#8.0提供了许多增强功能 1.Readonly 成员 可将 ...

  7. System.Collections深入探讨--如何创建自定义的集合类

    关键字:collection集合,ArrayList数组队列,Generic 泛型,List<T>列表,自定义集合类 正文:     在System.Collections namespa ...

  8. [corefx注释说]-System.Collections.Generic.StackT

    对C#里边的基础类库有充分的好奇心,所以就心血来潮写一下,这个就不定期更新了,想什么时候写就什么时候写好了.这里弱弱的吐槽一下CSDN的博客.为了以防万一,会在我其他的博客做一下备份. 废话不多说 切 ...

  9. C#命名空间 System.IO思维导图

    C#命名空间 System.IO思维导图 #mermaid-svg-43CMmjO0R5l1qNrR {font-family:"trebuchet ms",verdana,ari ...

最新文章

  1. java学习笔记(九)----多线程
  2. Nagios配置文件上传
  3. mysql级联查询_mysql 各种级联查询后更新(update select)
  4. mybatis多对多的问题汇总
  5. 高阶函数(Higher-order function)
  6. python多变量拟合_Python曲线将多个参数拟合到多个数据集
  7. 非精确运算和精确运算
  8. Android 实现静默安装
  9. 【裴礼文数学分析】例1.1.2
  10. 自媒体视频剪辑12大技巧分享
  11. 2月英语总结 —— 跟读 and topic
  12. 微软ime日文输入法在假名输入模式下怎么快速输入英文
  13. 运行时设置数据库连接字符串
  14. html文本输入框代码是什么?如何创建html文本输入框
  15. “全球化”是一个漫长过程,海尔智家用了20年
  16. 一文读懂 Java 反射机制那些事
  17. 知乎客户端埋点流程、模型和平台技术
  18. 嵌入式linux开发笔记——Ubuntu的使用
  19. 最好用的超大视频压缩软件
  20. Android 第三方应用接入微信平台(2)

热门文章

  1. 信息学奥赛一本通(2063:【例1.4】牛吃牧草)
  2. 图论 —— 网络流 —— 最大流 —— FF 算法与 EK 算法
  3. 烤鸡(洛谷-P2089)
  4. 信息学奥赛C++语言:斗转星移
  5. java的课后作业咋写_写的简单的java第三季的课后作业
  6. sklearn中ValueError: Unknown label type: ‘continuous‘错误解决
  7. 云计算交流会计算机操作,计算机二级考试真题-word-小王-云计算技术交流大会...
  8. opencv 扩大区域_python-----opencv图像边界扩充
  9. linux内核那些事之ZONE
  10. tf.cast() 数据类型转换