我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C#集合之并发集合的用法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C#集合之并发集合的用法

.NET 4 开始,在System.Collection.Concurrent中提供了几个线程安全的集合类。线程安全的集合可防止多个线程以相互冲突的方式访问集合。
为了对集合进行线程安全的访问,定义了IProducerConsumerCollection<T>接口。这个接口中最重要的方法是TryAdd()和TryTake()。TryAdd()方法尝试给集合添加一项,但如果集合禁止添加项,这个操作就可能失败。TryAdd()方法返回一个布尔值,以说明操作成功还是失败。TryTake()同样,在成功时返回集合中的项。

  • *ConcurrentQueue<T>————这个集合类用一种免锁定的算法实现,使用在内部合并到一个链表中的32项数组。该类有Enqueue(),TryDequeue()和TryPeek()方法。因为这个类实现了        IProducerConsumerCollection<T>接口,所以TryAdd()和TryTake()方法仅调用Enqueue和TryDequeue方法。
  • *ConcurrentStack<T>————类似于ConcurrentQueue<T>。该类定义了Push(),PushRange(),TryPeek(),TryPop()和TryPopRange()方法。在内部这个类使用其元素的链表。
  • *ConcurrentBag<T>————该类没有定义添加或提取项的任何顺序。这个类使用一个线程映射到内部使用的数组上的概念,因此尝试减少锁定。方法:Add(),TryPeek(),TryTake()。
  • *ConcurrentDictionary<TKey,TValue>————这是一个线程安全的键值集合。TryAdd(),TryGetValue(),TryRemove()和TryUpdate()方法以非阻塞的方式访问成员。因为元素基于键和值,所以ConcurrentDictionary<TKey,TValue>没有实现IProducerConsumerCollection<T>接口。
  • *BlockingCollection<T>————这个集合在可以添加或提取元素之前,会阻塞线程并一直等待。BlockingCollection<T>集合提供了一个接口,以使用Add()和Take()方法来删除和添加元素。这些方法会阻塞线程。Add()方法有一个重载版本,其中可以给该重载版本传递一个CancellationToken令牌。这个令牌允许取消被阻塞的调用。如果不希望无限的等待下去,且不希望从外部取消调用,就可以使用TryAdd()和TryTake()方法,在这些方法中,也可以指定一个超时值。

BlockingCollection<T>是对实现了 IProducerConsumerCollection<T>接口的任意类的修饰器,它默认使用ConcurrentQueue<T>类。还可以给构造函数传递任何实现了 IProducerConsumerCollection<T>接口的类。
下面使用一个例子演示BlockingCollection<T>的使用,一个任务向一个集合写入,同时另一个任务从这个集合读取。

    static void Main(string[] args)
        {
          StartPipeline();
          Console.ReadLine();
        }

        private static async void StartPipeline()
        {
            //存储文件名
          var fileNames = new BlockingCollection<string>();
          //存储文件的每一行内容
          var lines = new BlockingCollection<string>();
          //存储每一行的每个单词,单词为键,单词个数为值
          var words = new ConcurrentDictionary<string, int>();
          //存储words信息
          var items = new BlockingCollection<Info>();
          var coloredItems = new BlockingCollection<Info>();
            
          Task t1 = PipelineStages.ReadFilenamesAsync(@"../../..", fileNames);
          ConsoleHelper.WriteLine("started stage 1");
          Task t2 = PipelineStages.LoadContentAsync(fileNames, lines);
          ConsoleHelper.WriteLine("started stage 2");
          Task t3 = PipelineStages.ProcessContentAsync(lines, words);
          await Task.WhenAll(t1, t2, t3);
          ConsoleHelper.WriteLine("stages 1, 2, 3 completed");
        
          //当上面三个任务完成时,才执行下面的任务
          Task t4 = PipelineStages.TransferContentAsync(words, items);
          Task t5 = PipelineStages.AddColorAsync(items, coloredItems);
          Task t6 = PipelineStages.ShowContentAsync(coloredItems);
          ConsoleHelper.WriteLine("stages 4, 5, 6 started");

          await Task.WhenAll(t4, t5, t6);

          ConsoleHelper.WriteLine("all stages finished");
        }
        
        
          public static class PipelineStages
          {
            public static Task ReadFilenamesAsync(string path, BlockingCollection<string> output)
            {
              return Task.Run(() =>
                {
                  foreach (string filename in Directory.EnumerateFiles(path, "*.cs", SearchOption.AllDirectories))
                  {
                    output.Add(filename);
                    ConsoleHelper.WriteLine(string.Format("stage 1: added {0}", filename));
                  }
                  //调用CompleteAdding,通知所有读取器不应再等待集合中的任何额外项
                    //如果不调用该方法,读取器会在foreach循环中等待更多的项被添加
                  output.CompleteAdding();
                });
            }

            public static async Task LoadContentAsync(BlockingCollection<string> input, BlockingCollection<string> output)
            {
                //使用读取器读取集合时,需要使用GetConsumingEnumerable获取阻塞集合的枚举器,
            //如果直接使用input迭代集合,这只会迭代当前状态的集合,不会迭代以后添加的项
              foreach (var filename in input.GetConsumingEnumerable())
              {
                using (FileStream stream = File.OpenRead(filename))
                {
                  var reader = new StreamReader(stream);
                  string line = null;
                  while ((line = await reader.ReadLineAsync()) != null)
                  {
                    output.Add(line);
                    ConsoleHelper.WriteLine(string.Format("stage 2: added {0}", line));
                  }
                }
              }
              output.CompleteAdding();
            }

            public static Task ProcessContentAsync(BlockingCollection<string> input, ConcurrentDictionary<string, int> output)
            {
              return Task.Run(() =>
                {
                  foreach (var line in input.GetConsumingEnumerable())
                  {
                    string[] words = line.Split(' ', ';', '\t', '{', '}', '(', ')', ':', ',', '"');
                    foreach (var word in words.Where(w => !string.IsNullOrEmpty(w)))
                    {
                    //这里使用了字典的一个扩展方法
                      output.AddOrIncrementValue(word);
                      ConsoleHelper.WriteLine(string.Format("stage 3: added {0}", word));
                    }
                  }
                });
            }

            public static Task TransferContentAsync(ConcurrentDictionary<string, int> input, BlockingCollection<Info> output)
            {
              return Task.Run(() =>
                {
                  foreach (var word in input.Keys)
                  {
                    int value;
                    if (input.TryGetValue(word, out value))
                    {
                      var info = new Info { Word = word, Count = value };
                      output.Add(info);
                      ConsoleHelper.WriteLine(string.Format("stage 4: added {0}", info));
                    }
                  }
                  output.CompleteAdding();
                });
            }

            public static Task AddColorAsync(BlockingCollection<Info> input, BlockingCollection<Info> output)
            {
              return Task.Run(() =>
                {
                  foreach (var item in input.GetConsumingEnumerable())
                  {
                    if (item.Count > 40)
                    {
                      item.Color = "Red";
                    }
                    else if (item.Count > 20)
                    {
                      item.Color = "Yellow";
                    }
                    else
                    {
                      item.Color = "Green";
                    }
                    output.Add(item);
                    ConsoleHelper.WriteLine(string.Format("stage 5: added color {1} to {0}", item, item.Color));
                  }
                  output.CompleteAdding();
                });
            }

            public static Task ShowContentAsync(BlockingCollection<Info> input)
            {
              return Task.Run(() =>
                {
                  foreach (var item in input.GetConsumingEnumerable())
                  {
                    ConsoleHelper.WriteLine(string.Format("stage 6: {0}", item), item.Color);
                  }
                });
            }
          }
          
          
          //创建一个字典的扩展方法
         public static class ConcurrentDictionaryExtension
          {
            public static void AddOrIncrementValue(this ConcurrentDictionary<string, int> dict, string key)
            {
              bool success = false;
              while (!success)
              {
                int value;
                if (dict.TryGetValue(key, out value))
                {
                  if (dict.TryUpdate(key, value + 1, value))
                  {
                    success = true;
                  }
                }
                else
                {
                  if (dict.TryAdd(key, 1))
                  {
                    success = true;
                  }
                }
              }
            }
          }

这里使用了一个管道模型的编程模式,上面的添加内容,下面处理内容

到此这篇关于C#集合之并发集合的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C#集合之并发集合的用法

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

【Java】求两集合的交集、并集、差集

一、内置函数实现 1、removeAll方法:从list中删除指定集合中包含的所有元素。 2、retainAll方法:从list中删除指定集合中不包含的所有元素。 3、addAll方法:用来向Set集合添加另一个集合对象所包含的所有内容。
2023-08-18

使用python怎么求集合的并集

这篇文章将为大家详细讲解有关使用python怎么求集合的并集,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。1、说明可以使用 | 符号来计算两个或更多集合的并集,即将集合a和集合b中的元素合并
2023-06-15

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录