Как добавить элемент в очередь?

Я создаю службу Windows, которая использует FileSystemWatcher для контроля конкретной папки для добавления определенного типа файла. Из-за разрыва между созданным событием и когда файл действительно готов к обработке, я создал Queue<T> для хранения имен файлов, которые нуждаются в обработке. В обработчике созданного события элемент добавляется в очередь. Затем, используя таймер, я периодически захватываю первый элемент из очереди и обрабатываю его. Если обработка завершается неудачно, элемент добавляется обратно в очередь, чтобы служба могла повторить обработку позже.

Это отлично работает, но я обнаружил, что у него есть один побочный эффект: первая попытка обработки новых элементов происходит не до тех пор, пока все старые элементы повторной попытки не будут повторены. Поскольку возможно, что очередь может содержать много элементов, я бы хотел, чтобы новые элементы были впереди очереди, чтобы они обрабатывались первыми. Но из Queue<T> документации нет очевидного способа добавления элемента в очередь.

Я предполагаю, что я мог бы создать вторую очередь для новых элементов и обработать, что один предпочтительнее, но с одной очередью кажется более простым.

Итак, есть ли простой способ добавить элемент в очередь?

Ответ 1

Похоже, вы хотите LinkedList<T>, который позволяет делать такие вещи, как AddFirst(), AddLast(), RemoveFirst() и RemoveLast().

Ответ 2

Просто используйте метод Peek в обратном вызове таймера вместо Dequeue. Если обработка завершается успешно, то вычеркните элемент.

Ответ 3

Хорошо, я согласен с CanSpice; однако вы могли бы:

var items = queue.ToArray();
queue.Clear();
queue.Enqueue(newFirstItem);
foreach(var item in items)
    queue.Enqueue(item);

Неприятный взлом, но он будет работать;)

Скорее вы можете подумать о добавлении второго экземпляра очереди. Это одна очередь приоритетов, которую вы проверяете/выполняете в первую очередь. Это было бы немного чище. Вы даже можете создать свой собственный класс очереди, чтобы обернуть все это красиво и аккуратно;)

Ответ 4

Похоже, что вы находитесь после Stack - это буфер LIFO (последний, первый).

Ответ 5

Я бы предложил использовать две очереди: одну для новых элементов и одну для элементов повторной попытки. Оберните обе очереди в одном объекте, который имеет ту же семантику, что и очередь, до удаления, но позволяет отмечать вещи как входящие в очередь New или очередь Retry при вставке. Что-то вроде:

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

Конечно, вам нужно иметь свойство Count, которое возвращает количество элементов в обеих очередях.

Если у вас есть более двух типов элементов, тогда пришло время перейти на приоритетную очередь.

Ответ 6

Вам нужна очередь приоритетов. Взгляните на C5 Collections Library. IntervalHeap реализует интерфейс IPriorityQueue. Библиотека коллекций C5 тоже очень хороша.

Я считаю, что вы можете найти реализации в http://www.codeproject.com и http://www.codeplex.com.