BlockingCollection 使用
创建 BlockingCollection 的实例时通过构造函数指定最大容量,从而限制集合中项目的数量。
BlockingCollection
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
int maxCapacity = 5;
BlockingCollection<int> collection = new BlockingCollection<int>(maxCapacity);
Task producer = Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
collection.Add(i);
Console.WriteLine($"Produced: {i}");
}
collection.CompleteAdding();
});
Task consumer = Task.Run(() =>
{
foreach (var item in collection.GetConsumingEnumerable())
{
Console.WriteLine($"Consumed: {item}");
Thread.Sleep(500); // Simulate some work
}
});
Task.WaitAll(producer, consumer);
}
}
BlockingCollection
如果你想判断是否已经调用了 CompleteAdding() 方法,但集合中仍然有值,你可以使用 BlockingCollection
IsAddingCompleted:当调用了 CompleteAdding() 方法后,此属性将返回 true,即使集合中仍然有未消费的元素。
IsCompleted:当调用了 CompleteAdding() 方法且集合为空时,此属性将返回 true
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
BlockingCollection<int> collection = new BlockingCollection<int>();
Task producer = Task.Run(() =>
{
for (int i = 0; i < 5; i++)
{
collection.Add(i);
Console.WriteLine($"Produced: {i}");
}
collection.CompleteAdding();
});
Task consumer = Task.Run(() =>
{
while (!collection.IsCompleted)
{
if (collection.TryTake(out int item, TimeSpan.FromSeconds(1)))
{
Console.WriteLine($"Consumed: {item}");
}
else if (collection.IsAddingCompleted)
{
Console.WriteLine("Adding is completed but items still remain.");
}
}
Console.WriteLine("Collection is completed and empty.");
});
Task.WaitAll(producer, consumer);
}
}
在这个示例中,消费者任务在一个循环中检查 collection.IsCompleted 属性。如果集合未完成,尝试从集合中取出一个项目(带超时的 TryTake)。如果 TryTake 返回 false,并且 IsAddingCompleted 返回 true,这意味着已经调用了 CompleteAdding(),但集合中仍有未消费的元素。
当集合完成且为空时,collection.IsCompleted 将返回 true,消费者任务将输出 "Collection is completed and empty." 并结束。
BlockingCollection
无参数的 TryTake 方法:
不会阻塞。如果集合中没有项,立即返回 false。
带有超时参数的 TryTake 方法:
可以阻塞。它会等待指定的超时期限以尝试从集合中获取一个项。在此期间,如果集合变得非空,则返回该项;否则,在超时期限过后返回 false。
由于 BlockingCollection
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
BlockingCollection<int> collection = new BlockingCollection<int>(10); // 设置容量限制为10
// Producer tasks
Task producer1 = Task.Run(() => Produce(collection, 0));
Task producer2 = Task.Run(() => Produce(collection, 100));
// Consumer tasks
Task consumer1 = Task.Run(() => Consume(collection));
Task consumer2 = Task.Run(() => Consume(collection));
Task.WaitAll(producer1, producer2, consumer1, consumer2);
}
static void Produce(BlockingCollection<int> collection, int start)
{
for (int i = start; i < start + 10; i++)
{
collection.Add(i);
Console.WriteLine($"Produced: {i}");
Thread.Sleep(100); // 模拟一些工作
}
collection.CompleteAdding();
}
static void Consume(BlockingCollection<int> collection)
{
foreach (var item in collection.GetConsumingEnumerable())
{
Console.WriteLine($"Consumed: {item}");
Thread.Sleep(150); // 模拟一些工作
}
Console.WriteLine("Collection is completed and empty.");
}
}
通过这种方式,你可以在多个线程中安全地使用 Add 和 Take 操作,并且 BlockingCollection
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?