.NET Framework4.8.1排序缓冲区优化:替换轮询循环方案
.NET Framework 4.8.1 基于优先级阻塞集合的文件夹处理实现
针对遍历文件夹(生产者)速度快、处理(消费者)速度慢,需按访问时间优先排序且避免空循环的需求,以下是基于BlockingCollection结合自定义优先级集合的可运行实现:
1. 自定义线程安全优先级生产者消费者集合
这个集合实现IProducerConsumerCollection<T>,内部用SortedDictionary按访问时间排序,保证最早的元素优先被取出:
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; public class PriorityProducerConsumerCollection : IProducerConsumerCollection<(DateTime AccessTime, string FolderPath)> { private readonly SortedDictionary<DateTime, Queue<string>> _sortedQueues = new SortedDictionary<DateTime, Queue<string>>(); private readonly object _lock = new object(); public bool TryAdd((DateTime AccessTime, string FolderPath) item) { lock (_lock) { if (!_sortedQueues.TryGetValue(item.AccessTime, out var queue)) { queue = new Queue<string>(); _sortedQueues[item.AccessTime] = queue; } queue.Enqueue(item.FolderPath); } return true; } public bool TryTake(out (DateTime AccessTime, string FolderPath) item) { lock (_lock) { if (_sortedQueues.Count == 0) { item = default; return false; } var firstPair = _sortedQueues.First(); var folderPath = firstPair.Value.Dequeue(); item = (firstPair.Key, folderPath); if (firstPair.Value.Count == 0) { _sortedQueues.Remove(firstPair.Key); } return true; } } public int Count { get { lock (_lock) { return _sortedQueues.Sum(kv => kv.Value.Count); } } } public object SyncRoot => _lock; public bool IsSynchronized => true; public void CopyTo(Array array, int index) { throw new NotImplementedException(); } public void CopyTo((DateTime AccessTime, string FolderPath)[] array, int index) { throw new NotImplementedException(); } public IEnumerator<(DateTime AccessTime, string FolderPath)> GetEnumerator() { throw new NotImplementedException(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public (DateTime AccessTime, string FolderPath)[] ToArray() { lock (_lock) { var list = new List<(DateTime, string)>(); foreach (var kv in _sortedQueues) { foreach (var path in kv.Value) { list.Add((kv.Key, path)); } } return list.ToArray(); } } }
2. 主程序:生产者-消费者逻辑
生产者模拟遍历文件夹并添加元素,消费者通过BlockingCollection.GetConsumingEnumerable()阻塞等待元素,无需轮询:
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; class Program { static void Main(string[] args) { // 初始化优先级阻塞集合 var priorityCollection = new PriorityProducerConsumerCollection(); using var blockingCollection = new BlockingCollection<(DateTime AccessTime, string FolderPath)>(priorityCollection); // 启动消费者线程(处理速度慢) var consumerTask = Task.Factory.StartNew(() => { try { foreach (var item in blockingCollection.GetConsumingEnumerable()) { // 模拟实际处理逻辑,替换为你的业务代码 Console.WriteLine($"[处理中] 文件夹: {item.FolderPath} | 访问时间: {item.AccessTime:yyyy-MM-dd HH:mm:ss}"); Thread.Sleep(1000); // 模拟处理耗时 Console.WriteLine($"[处理完成] 文件夹: {item.FolderPath}"); } } catch (InvalidOperationException) { // 集合已完成添加且为空时,GetConsumingEnumerable会抛出此异常,可忽略 } Console.WriteLine("[消费者] 所有文件夹处理完成,线程退出"); }, TaskCreationOptions.LongRunning); // 生产者线程(遍历速度快) var producerTask = Task.Factory.StartNew(() => { // 模拟遍历得到的文件夹列表,实际中替换为真实的文件夹遍历逻辑 var folders = new List<(DateTime AccessTime, string FolderPath)> { (new DateTime(2024, 5, 20, 10, 30, 0), @"C:\Workspace\Folder1"), (new DateTime(2024, 5, 18, 9, 15, 0), @"C:\Workspace\Folder2"), (new DateTime(2024, 5, 21, 14, 45, 0), @"C:\Workspace\Folder3"), (new DateTime(2024, 5, 19, 16, 20, 0), @"C:\Workspace\Folder4"), (new DateTime(2024, 5, 18, 8, 50, 0), @"C:\Workspace\Folder5") }; foreach (var folder in folders) { Console.WriteLine("[生产者] 发现文件夹: {0} | 访问时间: {1:yyyy-MM-dd HH:mm:ss}", folder.FolderPath, folder.AccessTime); blockingCollection.Add(folder); Thread.Sleep(200); // 模拟遍历速度快于处理速度 } // 通知消费者:没有更多元素需要添加 blockingCollection.CompleteAdding(); Console.WriteLine("[生产者] 文件夹遍历完成,线程退出"); }, TaskCreationOptions.LongRunning); // 等待所有任务执行完毕 Task.WaitAll(producerTask, consumerTask); Console.WriteLine("程序执行结束"); } }
关键特性说明
- 无空循环:消费者通过
GetConsumingEnumerable()自动阻塞,直到有元素或集合标记为完成添加,彻底避免轮询空转。 - 优先级排序:自定义集合基于
SortedDictionary按访问时间升序排列,保证最早访问的文件夹优先被处理。 - 线程安全:内部通过
lock保证多线程环境下的集合操作安全,结合BlockingCollection的线程安全封装,适配生产者-消费者模型。 - 兼容.NET Framework 4.8.1:所有使用的类(
BlockingCollection、Task等)均为该框架原生支持,无需额外依赖。
内容的提问来源于stack exchange,提问作者NilNul
相关产品推荐
相关产品推荐

