在C#中,BlockingCollection类可以很好地实现生产者消费者模式。它是一个线程安全的集合,可以在多个线程之间安全地传递数据。以下是一个简单的示例:
首先,创建一个名为ProducerConsumerExample
的类,并在其中定义两个方法:Produce
和Consume
,分别用于生产数据和消费数据。
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
class ProducerConsumerExample
{
private static BlockingCollection<int> _blockingCollection = new BlockingCollection<int>();
static void Main(string[] args)
{
// 创建两个任务,一个用于生产数据,另一个用于消费数据
Task producerTask = Task.Run(() => Produce());
Task consumerTask = Task.Run(() => Consume());
// 等待两个任务完成
Task.WaitAll(producerTask, consumerTask);
}
static void Produce()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine($"Producing: {i}");
_blockingCollection.Add(i);
Thread.Sleep(1000); // 模拟生产过程耗时
}
// 生产完成后,通知消费者任务已完成
Console.WriteLine("All items produced.");
_blockingCollection.CompleteAdding();
}
static void Consume()
{
foreach (var item in _blockingCollection.GetConsumingEnumerable())
{
Console.WriteLine($"Consuming: {item}");
Thread.Sleep(2000); // 模拟消费过程耗时
}
Console.WriteLine("All items consumed.");
}
}
在这个示例中,我们使用了一个名为_blockingCollection
的BlockingCollection<int>
实例来存储数据。Produce
方法用于生产数据,将数据添加到BlockingCollection
中。Consume
方法用于消费数据,从BlockingCollection
中获取数据并处理。
BlockingCollection
提供了CompleteAdding
方法,当生产完成后调用此方法,可以通知消费者任务已完成。GetConsumingEnumerable
方法返回一个可枚举的序列,该序列会在BlockingCollection
中有新元素时自动更新。这样,消费者可以在有新数据时立即开始处理,而不需要不断检查是否有新数据。
在Main
方法中,我们创建了两个任务,一个用于生产数据,另一个用于消费数据,并使用Task.WaitAll
等待它们完成。