如何将项目添加到队列的前面?

Cor*_*rin 14 c#

我正在创建一个Windows服务,它使用FileSystemWatcher监视特定文件夹以添加特定文件类型.由于Created事件与文件实际准备好被操作之间的差距,我创建了一个Queue<T>来保存需要处理的文件名.在Created事件处理程序中,该项目将添加到队列中.然后使用计时器,我定期从队列中抓取第一个项目并进行处理.如果处理失败,则将项目添加回队列,以便服务稍后可以重试处理.

这工作正常,但我发现它有一个副作用:新项目的第一次处理尝试不会发生,直到所有旧的重试项目都被重试.由于队列可能包含许多项目,因此我想将新项目强制到队列的前面,以便首先处理它们.但是从Queue<T>文档中,没有明显的方法将项添加到队列的前面.

我想我可以为新项创建第二个队列,并优先处理一个,但是单个队列似乎更简单.

那么有一种简单的方法可以将项目添加到队列的前面吗?

Can*_*ice 35

它看起来像你想要一个LinkedList<T>,它允许你做像AddFirst(),AddLast()RemoveFirst(),和RemoveLast().

  • 作为额外的奖励,LinkedList <T>是双重链接的,因此上面列出的所有操作都是O(1). (2认同)

500*_*ror 7

只需在计时器回调中使用Peek方法而不是Dequeue.如果处理成功,则将项目出列.


小智 7

在处理之前不要从队列中取出它,这是另一种解决方案。

queue.Peek()Dequeue()当操作成功时才​​用于获取您的第一个项目。

queue.Count > 0在您之前使用Peek(),否则您将得到“队列为空”的结果。


csh*_*net 6

好吧,我同意 CanSpice;但是,您可以:

var items = queue.ToArray();
queue.Clear();
queue.Enqueue(newFirstItem);
foreach(var item in items)
    queue.Enqueue(item);
Run Code Online (Sandbox Code Playgroud)

讨厌的黑客,但它会起作用;)

相反,您可能会考虑添加第二个队列实例。这是您首先检查/执行的“优先级”队列。这样会干净一些。你甚至可以创建你自己的队列类来把它全部包起来,就像;)


Jim*_*hel 5

我建议使用两个队列:一个用于新项目,一个用于重试项目。将两个队列包装在一个对象中,该对象在删除方面与队列具有相同的语义,但允许您将事物标记为进入新队列或插入时的重试队列。就像是:

public class DoubleQueue<T>
{
    private Queue<T> NewItems = new Queue<T>();
    private Queue<T> RetryItems = new Queue<T>();

    public Enqueue(T item, bool isNew)
    {
        if (isNew)
            NewItems.Enqueue(item);
        else
            RetryItems.Enqueue(item);
    }

    public T Dequeue()
    {
        if (NewItems.Count > 0)
            return NewItems.Dequeue();
        else
            return RetryItems.Dequeue();
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,您需要有一个Count属性来返回两个队列中的项目数。

如果您有两种以上类型的项目,那么就该升级到优先级队列了。