好医生网站怎么做不了题目了,图标设计免费logo,哪些公司的网站做的很好,噼里啪啦动漫在线观看免费什么是 BlockingCollectionT主要特点构造函数常用方法生产者操作消费者操作 示例代码注意事项串口接收底层存储的类型线程安全和并发访问串口数据接收的顺序性关键点 BlockingCollectionT 是
C# 中一个非常有用的线程安全集合类#xff0c;位于
System.Coll… 什么是 BlockingCollectionT主要特点构造函数常用方法生产者操作消费者操作 示例代码注意事项串口接收底层存储的类型线程安全和并发访问串口数据接收的顺序性关键点 BlockingCollectionT 是
C# 中一个非常有用的线程安全集合类位于
System.Collections.Concurrent 命名空间中。它主要用于在多线程环境中实现
线程安全的生产者-消费者模式。 以下是关于
BlockingCollectionT 的详细介绍 什么是 BlockingCollectionT
BlockingCollectionT 是一个线程安全的集合它提供了一种机制允许一个或多个生产者线程将数据添加到集合中同时允许一个或多个消费者线程从集合中取出数据。它内部封装了一个线程安全的集合如 ConcurrentQueueT、ConcurrentStackT 或 ConcurrentBagT并提供了阻塞和限制集合大小的功能。
主要特点
线程安全内部使用锁或其他同步机制确保在多线程环境下对集合的操作是安全的。阻塞操作当集合为空时消费者线程会阻塞等待直到有数据可用当集合达到最大容量时生产者线程会阻塞等待直到有空间可用。限制大小可以通过构造函数指定集合的最大容量。支持多种底层集合可以使用 ConcurrentQueueT默认、ConcurrentStackT 或 ConcurrentBagT 作为底层存储结构。
构造函数
BlockingCollectionT 提供了多种构造方式
// 使用默认的 ConcurrentQueueT无容量限制
var blockingCollection new BlockingCollectionint();// 使用默认的 ConcurrentQueueT并指定最大容量
var blockingCollection new BlockingCollectionint(10);// 指定底层集合类型
var blockingCollection new BlockingCollectionint(new ConcurrentStackint());常用方法
生产者操作
Add(T item)将一个元素添加到集合中。如果集合已满会抛出异常。 TryAdd(T item)尝试将一个元素添加到集合中。如果集合已满返回 false。 TryAdd(T item, TimeSpan timeout)尝试在指定的超时时间内将元素添加到集合中。 CompleteAdding()标记集合不再添加新的元素。消费者线程在集合为空时会收到通知并退出。
消费者操作
Take()从集合中取出一个元素。如果集合为空线程会阻塞等待。 TryTake(out T item)尝试从集合中取出一个元素。如果集合为空返回 false。 TryTake(out T item, TimeSpan timeout)尝试在指定的超时时间内从集合中取出一个元素。 GetConsumingEnumerable()返回一个可枚举的集合消费者可以使用 foreach 遍历集合中的元素。当调用 CompleteAdding() 后枚举会结束。
示例代码
以下是一个简单的生产者-消费者示例使用 BlockingCollectionT 实现
using System;
using System.Collections.Concurrent;
using System.Threading;class Program
{static void Main(){// 创建一个容量为 5 的 BlockingCollectionvar blockingCollection new BlockingCollectionint(5);// 启动生产者线程Thread producerThread new Thread(() {for (int i 1; i 10; i){blockingCollection.Add(i); // 添加元素Console.WriteLine($Producer added: {i});Thread.Sleep(500); // 模拟生产时间}blockingCollection.CompleteAdding(); // 标记不再添加元素});// 启动消费者线程Thread consumerThread new Thread(() {foreach (var item in blockingCollection.GetConsumingEnumerable()){Console.WriteLine($Consumer consumed: {item});Thread.Sleep(1000); // 模拟消费时间}});producerThread.Start();consumerThread.Start();producerThread.Join();consumerThread.Join();}
}输出示例
Producer added: 1
Producer added: 2
Consumer consumed: 1
Producer added: 3
Consumer consumed: 2
Producer added: 4
Consumer consumed: 3
Producer added: 5
Consumer consumed: 4
Producer added: 6
Consumer consumed: 5
Producer added: 7
Consumer consumed: 6
Producer added: 8
Consumer consumed: 7
Producer added: 9
Consumer consumed: 8
Producer added: 10
Consumer consumed: 9
Consumer consumed: 10注意事项
线程安全BlockingCollectionT 是线程安全的但需要确保对集合的操作不会与其他非线程安全的操作混用。容量限制如果集合满了生产者线程会阻塞因此需要合理设置容量。异常处理在生产者调用 Add() 或消费者调用 Take() 时可能会抛出异常如集合已满或已标记为完成添加。建议使用 TryAdd() 和 TryTake() 方法来避免异常。 BlockingCollectionT 是 C# 中实现线程安全的生产者-消费者模式的利器它简化了线程同步的复杂性非常适合多线程编程场景。 串口接收
在使用 BlockingCollectionT 存储串口接收的数据并在其他线程中取出时是否能保证数据的顺序主要取决于以下两个因素
底层存储的类型
BlockingCollectionT 允许指定底层存储的类型。默认情况下它使用 ConcurrentQueueT 作为底层存储而 ConcurrentQueueT 是一个先进先出 FIFO的队列。这意味着数据的添加顺序和取出顺序是一致的因此可以保证顺序。 如果你使用其他类型的底层存储如 ConcurrentStackT 或自定义的线程安全集合则顺序可能会有所不同。例如 ConcurrentQueueT保证 FIFO 顺序。 ConcurrentStackT保证 LIFO后进先出顺序。
线程安全和并发访问
BlockingCollectionT 是线程安全的因此即使在多线程环境下数据的添加和取出操作也是安全的。只要底层存储是 FIFO 的如 ConcurrentQueueT数据的顺序就能得到保证。
串口数据接收的顺序性
串口通信本身是按字节顺序接收数据的因此只要数据是逐字节接收并立即添加到 BlockingCollectionT 中数据的顺序就能得到保证。 示例代码 以下是一个示例展示如何使用 BlockingCollectionT 存储串口接收的数据并在其他线程中按顺序取出
using System;
using System.Collections.Concurrent;
using System.IO.Ports;
using System.Threading;class SerialPortExample
{private SerialPort _serialPort;private BlockingCollectionstring _dataQueue new BlockingCollectionstring();public SerialPortExample(string portName){_serialPort new SerialPort(portName){BaudRate 9600,DataBits 8,Parity Parity.None,StopBits StopBits.One,ReadTimeout 500};_serialPort.DataReceived SerialPort_DataReceived;}private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){try{string data _serialPort.ReadLine(); // 假设数据以换行符分隔_dataQueue.Add(data); // 将数据添加到阻塞集合Console.WriteLine($Received and added: {data});}catch (Exception ex){Console.WriteLine($Error in DataReceived: {ex.Message});}}public void Start(){_serialPort.Open();Thread consumerThread new Thread(ConsumeData);consumerThread.Start();}private void ConsumeData(){foreach (var data in _dataQueue.GetConsumingEnumerable()){Console.WriteLine($Consumed: {data});// 处理数据}}public void Stop(){_dataQueue.CompleteAdding();_serialPort.Close();}static void Main(){SerialPortExample example new SerialPortExample(COM3);example.Start();Console.WriteLine(Press Enter to exit...);Console.ReadLine();example.Stop();}
}关键点
底层存储使用 ConcurrentQueueT默认可以保证数据的 FIFO 顺序。线程安全BlockingCollectionT 是线程安全的因此在多线程环境下不会出现数据顺序混乱的问题。串口数据接收只要串口接收的数据是按顺序添加到 BlockingCollectionT 中的顺序就能得到保证。
因此只要使用默认的 ConcurrentQueueT 作为底层存储并且正确处理串口数据的接收和添加BlockingCollectionT 是可以保证数据顺序的。