重庆熊猫 Loading

.NET中的并发操作集合

更新记录
本文迁移自Panda666原博客,原发布时间:2021年7月1日。

一、并发集合

.NET中提供了相当多线程安全的集合,它们都在System.Collections.Concurrent命名空间下。具体的类型进行可以到.NET官方API浏览器:点击这里访问查看。

具体类型如下:
image

二、多任务写入/读取ConcurrentQueue

这里使用支持并发的队列ConcurrentQueue作为例子,通过2个Task进行进队任务,再通过2个Task进行出队的任务。

using System;
using System.Threading.Tasks;
using System.Collections.Concurrent;

namespace PadnaTestClass
{
    class Program
    {
        static void Main(string[] args)
        {

            //用于写入的集合
            ConcurrentQueue<string> concurrentQueue = new ConcurrentQueue<string>();

            //=========================进队操作==========================
            //新建进队任务1
            Task taskForEnqueue1 = Task.Run(() => {
                for (int i = 0; i <= 10000; i++)
                {
                    //存入和输出的内容
                    string content = $"进队任务1,当前执行到{i}";
                    //进队
                    concurrentQueue.Enqueue(content);
                    //输出操作过程
                    Console.WriteLine(content);
                }    
            });

            //新建进队任务2
            Task taskForEnqueue2 = Task.Run(() => {
                for (int i = 0; i <= 10000; i++)
                {
                    //存入和输出的内容
                    string content = $"进队任务2,当前执行到{i}";
                    //进队
                    concurrentQueue.Enqueue(content);
                    //输出操作过程
                    Console.WriteLine(content);
                }
            });

            //等待写入任务完成
            Task.WaitAll(new Task[] { taskForEnqueue1, taskForEnqueue2 });
            //=========================进队操作==========================

            //=========================出队操作===================
            //新建出队任务1
            Task taskForDequeue1 = Task.Run(() => {
                while (concurrentQueue.Count != 0)
                {
                    if (concurrentQueue.TryDequeue(out string result))
                    {
                        Console.WriteLine("出队任务1-" + result);
                    }
                }
            });
            
            //新建出队任务2
            Task taskForDequeue2 = Task.Run(() => {
                while (concurrentQueue.Count != 0)
                {
                    if (concurrentQueue.TryDequeue(out string result))
                    {
                        Console.WriteLine("出队任务2-" + result);
                    }
                }
            });
            //=========================出队操作====================

            //wait
            Console.ReadKey();
        }
    }
}
```

### 三、多任务写入/读取ConcurrentDictionary 
这里使用支持并发的字典ConcurrentDictionary作为例子,通过2个Task进行写入元素数据任务,再通过2个Task进行读取和移除元素的任务。
```c#
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Collections.Concurrent;

namespace PadnaTestClass
{
    class Program
    {
        static void Main(string[] args)
        {
            //用于写入的集合
            ConcurrentDictionary<string,string> concurrentDictionary = new ConcurrentDictionary<string,string>();

            //==========添加数据操作=================
            //新建用于写入数据的任务1
            Task taskForAddData1 = Task.Run(() => {
                for (int i = 0; i <= 10000; i++)
                {
                    //存入和输出的内容
                    string dataKey = $"任务1的-{i}-Key";
                    string dataValue = $"任务1的-{i}-Value";
                    //加入数据到并发集合中
                    concurrentDictionary.TryAdd(dataKey, dataValue);
                    //输出操作过程
                    Console.WriteLine(dataKey + " || " + dataValue);
                }    
            });

            //新建用于写入数据的任务2
            Task taskForAddData2 = Task.Run(() => {
                for (int i = 0; i <= 10000; i++)
                {
                    //存入和输出的内容
                    string dataKey = $"任务2的-{i}-Key";
                    string dataValue = $"任务2的-{i}-Value";
                    //加入数据到并发集合中
                    concurrentDictionary.TryAdd(dataKey, dataValue);
                    //输出操作过程
                    Console.WriteLine(dataKey + " || " + dataValue);
                }
            });

            //等待写入任务完成
            Task.WaitAll(new Task[] { taskForAddData1, taskForAddData2 });
            //==============添加数据操作=================
            //=============读取并移除数据操作============
            //新建读取并删除元素任务1
            Task taskForReadData1 = Task.Run(() => {
                foreach (string dataKey in concurrentDictionary.Keys)
                {
                    if (concurrentDictionary.TryGetValue(dataKey, out string dataValue))
                    {
                        //输出值
                        Console.WriteLine(dataValue);
                        //移除值
                        concurrentDictionary.TryRemove(new KeyValuePair<string, string>(dataKey,dataValue));
                    }
                }
            });

            //新建读取并删除元素任务2
            Task taskForReadData2 = Task.Run(() => {
                foreach (string dataKey in concurrentDictionary.Keys)
                {
                    if (concurrentDictionary.TryGetValue(dataKey, out string dataValue))
                    {
                        //输出值
                        Console.WriteLine(dataValue);
                        //移除值
                        concurrentDictionary.TryRemove(new KeyValuePair<string, string>(dataKey, dataValue));
                    }
                }
            });
            //==========读取并移除数据操作=========

            //等待任务完成
            Task.WaitAll(taskForReadData1, taskForReadData2);
            //读取集合元素的个数
            Console.WriteLine(concurrentDictionary.Count); //0

            //wait
            Console.ReadKey();
        }
    }
}
posted @ 2022-04-16 16:38  重庆熊猫  阅读(165)  评论(0编辑  收藏  举报