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

c3frrgcw  于 2023-02-27  发布在  .NET
关注(0)|答案(4)|浏览(153)

我相信一个非常常见的场景是有一个项目队列,应该一次处理N个项目。
例如,如果我们有23 items,并且应该一次处理10,则如下所示:

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

我可以用很多方法来解决这个问题。我的问题是:NET框架是否提供了专门针对这种情况设计的类?Queue类是最好的,但它不允许一次将多个项目出队。

yyhrrdl8

yyhrrdl81#

您可以在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
41zrol4v

41zrol4v2#

您可以在.NET中使用Linq通过使用Enumerable.Range()方法沿着Select()扩展方法来实现这一点:
var chunk = Enumerable.Range(0, chuckCount).Select(i => queue.Dequeue()).ToList();
它的工作原理是生成一个整数的可枚举对象,然后为新的可枚举对象中的每个整数将一个项目从队列中出队。通过调用ToList()确保操作立即完成。

jmp7cifd

jmp7cifd3#

TPL Dataflow库提供了BatchBlock < T >,它将消息的输入序列分组为所需大小的块。

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();
u59ebvdq

u59ebvdq4#

我可能只使用一个简化的版本来将队列中的内容出队,并使用计时器或您正在使用的系统中可用的任何东西以特定的间隔执行此操作。
因此,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();
        }
    }

相关问题