Here's a simple generic PriorityQueue<T> class that I created when I needed some of this basic functionality recently.

Code:
internal enum PriorityLevel
{
    Low,
    Medium,
    High
}

internal class PriorityQueue<T> : ICollection, IReadOnlyCollection<T>
{
    private readonly Dictionary<PriorityLevel, Queue<T>> _priorityQueues;

    public int Count
    {
        get
        {
            return _priorityQueues[PriorityLevel.High].Count
                 + _priorityQueues[PriorityLevel.Medium].Count
                 + _priorityQueues[PriorityLevel.Low].Count;
        }
    }
    
    public PriorityQueue()
        : this(64)
    { }
    
    public PriorityQueue(int capacity)
    {
        _priorityQueues = new Dictionary<PriorityLevel, Queue<T>>(3)
        {
            { PriorityLevel.Low,    new Queue<T>(capacity) },
            { PriorityLevel.Medium, new Queue<T>(capacity) },
            { PriorityLevel.High,   new Queue<T>(capacity) }
        };
    }
    
    public void Clear()
    {
        _priorityQueues[PriorityLevel.Low].Clear();
        _priorityQueues[PriorityLevel.Medium].Clear();
        _priorityQueues[PriorityLevel.High].Clear();
    }
    
    public void Enqueue(PriorityLevel priority, T item)
    {
        _priorityQueues[priority].Enqueue(item);
    }

    public T Dequeue()
    {
        if (_priorityQueues[PriorityLevel.High].Count != 0)
            return _priorityQueues[PriorityLevel.High].Dequeue();
        
        if (_priorityQueues[PriorityLevel.Medium].Count != 0)
            return _priorityQueues[PriorityLevel.Medium].Dequeue();
        
        return _priorityQueues[PriorityLevel.Low].Dequeue();
    }

    public T Peek()
    {
        if (_priorityQueues[PriorityLevel.High].Count != 0)
            return _priorityQueues[PriorityLevel.High].Peek();
        
        if (_priorityQueues[PriorityLevel.Medium].Count != 0)
            return _priorityQueues[PriorityLevel.Medium].Peek();
        
        return _priorityQueues[PriorityLevel.Low].Peek();
    }
    
    public IEnumerator<T> GetEnumerator()
    {
        foreach (var item in _priorityQueues[PriorityLevel.High])
            yield return item;
        
        foreach (var item in _priorityQueues[PriorityLevel.Medium])
            yield return item;
        
        foreach (var item in _priorityQueues[PriorityLevel.Low])
            yield return item;
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public void CopyTo(Array array, int index)
    {
        using (var enumerator = GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                array.SetValue(enumerator.Current, index++);
            }
        }
    }

    int ICollection.Count { get { return Count; } }

    public object SyncRoot { get { return this; }  }
    public bool IsSynchronized { get { return false; } }
    int IReadOnlyCollection<T>.Count { get { return Count; } }
}
Works pretty decent for what it is.