C# 任务队列操作:完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

C# 任务队列简介



在现代多线程编程中,任务队列(task queue)是组织异步数据处理的基础模式。在 C# (.NET) 中,该模式通过多种强大机制实现,使开发者能够高效管理执行线程并分配负载。



任务队列解决了经典的 producer-consumer(生产者-消费者)问题,其中一部分代码创建任务,另一部分代码处理任务。在本文中,我们将探讨 C# 中实现任务队列的主要方式:从简单集合到现代通道(Channel)。



实现任务队列的主要方法



1. ConcurrentQueue — 线程安全队列



最简单且低级的实现是来自 System.Collections.Concurrent 命名空间的 ConcurrentQueue<T>。它提供了线程安全的 Enqueue 和 TryDequeue 方法。



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

public class SimpleTaskQueue{ private readonly ConcurrentQueue<Action> _tasks = new(); private readonly Task _worker;

public SimpleTaskQueue() { _worker = Task.Run(ProcessTasks); }

public void Enqueue(Action task) { _tasks.Enqueue(task); }

private void ProcessTasks() { while (true) { if (_tasks.TryDequeue(out var task)) { task(); } } }}


优点:

  • 使用简单
  • 内存消耗低
  • 无锁线程安全


缺点:

  • 循环中的忙等待(busy waiting)
  • 缺少新任务通知机制
  • 停止操作复杂


2. BlockingCollection — 阻塞队列



BlockingCollection<T> 解决了忙等待问题。它提供了 Add 和 Take 方法,这些方法会在数据可用前阻塞线程。



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

public class BlockingTaskQueue : IDisposable{ private readonly BlockingCollection<Action> _tasks = new(new ConcurrentQueue<Action>()); private readonly Task[] _workers; private bool _disposed;

public BlockingTaskQueue(int workerCount = 4) { _workers = new Task[workerCount]; for (int i = 0; i < workerCount; i++) { _workers[i] = Task.Run(ProcessTasks); } }

public void Enqueue(Action task) { _tasks.Add(task); }

private void ProcessTasks() { foreach (var task in _tasks.GetConsumingEnumerable()) { if (_disposed) break; task(); } }

public void CompleteAdding() { _tasks.CompleteAdding(); }

public void Dispose() { _disposed = true; _tasks.CompleteAdding(); Task.WaitAll(_workers); _tasks.Dispose(); }}


关键特性:

  • 无任务时自动阻塞线程
  • 支持通过 CancellationToken 取消
  • 可限制队列容量
  • 通过 CompleteAdding 安全终止


现代方法:Channel<T>



从 .NET Core 3.0 和 .NET 5 开始,C# 引入了 System.Threading.Channels.Channel<T> — 这是最高性能和最灵活的任务队列实现。它支持异步操作、取消和限制吞吐量。

博客

书籍推荐