You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 04:20:19