Skip to content

多线程 - BlockingCollection

  • BlockingCollection 是线程安全的,多个线程可以同时安全地向集合中添加或取出数据。

  • 如果集合达到容量上限,生产者线程会阻塞,直到有空间可以添加数据。

  • 如果集合为空,消费者线程会阻塞,直到有数据可用

  • 可以设置最大容量限制,用于控制集合的大小。

  • 内部通过 IProducerConsumerCollection 实现,并发访问时无需额外的锁。

csharp
BlockingCollection<T>.Count
BlockingCollection<T>.Add()
BlockingCollection<T>.Take()
BlockingCollection<T>.TryTake(out T item, int millisecondsTimeout)
csharp
// 创建一个容量为5的 BlockingCollection
BlockingCollection<int> collection = new BlockingCollection<int>(5);

// 启动生产者线程
Task producer = Task.Run(() =>
{
    for (int i = 0; i < 10; i++)
    {
        collection.Add(i); // 添加数据到集合
        Console.WriteLine($"Produced: {i}");
        Thread.Sleep(100); // 模拟生产延迟
    }
    collection.CompleteAdding(); // 标记完成添加
});

// 启动消费者线程
Task consumer = Task.Run(() =>
{
    while (!collection.IsCompleted)
    {
        try
        {
            int item = collection.Take(); // 从集合中取出数据
            Console.WriteLine($"Consumed: {item}");
        }
        catch (InvalidOperationException)
        {
            // 集合已完成,捕获异常并退出
            break;
        }
    }
});

// 等待任务完成
Task.WaitAll(producer, consumer);

Console.WriteLine("Processing complete.");

底层集合

BlockingCollection 可以使用不同的底层集合。常见的底层集合有:

  • ConcurrentQueue(默认):先进先出(FIFO)。
  • ConcurrentStack:后进先出(LIFO)。
  • ConcurrentBag:无序集合。

使用 ConcurrentStack 作为底层集合

csharp
BlockingCollection<int> collection = new BlockingCollection<int>(new ConcurrentStack<int>());

上次更新时间:

最近更新