是否有一个.NET队列类允许一次将多个项目出列

本文关键字:项目 许一次 NET 有一个 队列 是否 | 更新日期: 2023-09-27 18:20:48

我认为一个非常常见的场景是有一个项目队列,应该一次处理N个。

例如。。如果我们有23 items,并且应该一次处理10,它会像:

Process batch of 10
Process batch of 10
Process batch of 3

我可以用多种方法解决这个问题。我的问题是:.NET框架是否提供了专门为解决这种情况而设计的类?Queue类将是完美的,但它不允许同时对多个项目进行排队。

是否有一个.NET队列类允许一次将多个项目出列

您可以在Queue<T>:上创建一个扩展方法

public static class QueueExtensions
{
    public static IEnumerable<T> DequeueChunk<T>(this Queue<T> queue, int chunkSize) 
    {
        for (int i = 0; i < chunkSize && queue.Count > 0; i++)
        {
            yield return queue.Dequeue();
        }
    }
}

用法:

var q = new Queue<char>();
q.DequeueChunk(10) // first 10 items
q.DequeueChunk(10) // next 10 items

示例:https://dotnetfiddle.net/OTcIZX

您可以在带有Linq的.NET中通过使用Enumerable.Range()方法和Select()扩展方法来实现这一点:

var chunk = Enumerable.Range(0, chuckCount).Select(i => queue.Dequeue()).ToList();

这是通过生成一个可枚举的整数来实现的,然后对于新的可枚举中的每个整数,它将一个项目从队列中移出。通过调用ToList()确保立即完成该操作。

TPL数据流库提供BatchBlock<将输入的消息序列分组为所需大小的块。

 var bb = new BatchBlock<int>(10);
 var ab = new ActionBlock<int[]>((Action<int[]>)chunk=>HandleChunk(chunk));  
 bb.LinkTo(ab, new DataflowLinkOptions(){PropogateCompletion = true});
 for(int i = 0; i < 23; ++i)
 {
     bb.Post(i);
 }
 bb.Complete();
 ab.Completion.Wait();

我可能只需要使用一个简化的版本来将队列中的内容出列,并使用计时器或您使用的系统中可用的任何东西以特定的间隔进行。

因此,10秒后,如果有10秒,则出列并处理,或者如果有100秒,则执行相同操作。这一切都取决于负载、正在完成的工作等,以及对延迟的期望,以及对您试图实现的目标的响应等

我认为,使用您这样做的队列不会立即产生结果,而是可以在更长的时间内执行的东西,比如数据聚合。

这样就没有严格的SLA窗口。可能需要一些基准测试和测试来了解负载是什么以及首选的时间间隔是什么。

    public static IEnumerable<T> DequeueAvailable<T>(this Queue<T> queue)
    {
        for (int i = 0; i < queue.Count; i++)
        {
            yield return queue.Dequeue();
        }
    }