对于我们一直在研究的项目,我们使用了并发字典,这很好,直到新的规范出现,需要对字典进行排序(它应该按照添加的顺序保留,有点像一个FIFO)。
这是我们目前的工作,我们从字典中取出x个数量(在这种情况下为5个)项目:
private Dictionary<PriorityOfMessage, ConcurrentDictionary<Guid, PriorityMessage>> mQueuedMessages = new Dictionary<PriorityOfMessage, ConcurrentDictionary<Guid, PriorityMessage>>();
var messages = new List<KeyValuePair<Guid, PriorityMessage>>();
messages.AddRange(mQueuedMessages[priority].Take(5));
然后我们用它做一些事情,最终如果一切顺利,我们就把它们删除了。
mQueuedMessages[priority].TryRemove(messageOfPriority.Key);
然而,如果事情失败,我们不会删除它们并稍后再尝试。所以不幸的是没有并发的排序字典,但是有没有办法确保消息按照添加的顺序保留?
非常重要的是我们可以从列表/字典中获取多个对象而不删除它们(或者我们需要能够将它们添加到前面)。
答案 0 :(得分:3)
你每周多少次一次?
它可能是每秒一千次
每秒1000次锁定操作绝对没有。这几乎不会消耗任何时间。
我的同事已经尝试使用锁和列表,他认为它太慢了
这很可能意味着锁定区域太大了。我的猜测是这样的:
lock (...) {
var item = TakeFromQueue();
Process(item);
DeleteFromQueue(item);
}
这不起作用,因为Process
太慢了。必须是:
lock (...)
var item = TakeFromQueue();
Process(item);
lock (...)
DeleteFromQueue(item);
根本不存在任何性能问题。
您现在可以选择您喜欢的任何数据结构。您不再受内置并发数据结构的功能约束。除了选择您喜欢的数据结构外,您还可以对其进行任何操作,例如以原子方式获取多个项目。
我还没有完全理解你的需求,但听起来SortedList
可能会朝着正确的方向发展。
答案 1 :(得分:-1)
你也可以寻求另一种解决方案(避免在性能方面进行测试):
public class ConcurrentIndexableQueue<T> {
private long tailIndex;
private long headIndex;
private readonly ConcurrentDictionary<long, T> dictionary;
public ConcurrentIndexableQueue() {
tailIndex = -1;
headIndex = 0;
dictionary = new ConcurrentDictionary<long, T>();
}
public long Count { get { return tailIndex - headIndex + 1; } }
public bool IsEmpty { get { return Count == 0; } }
public void Enqueue(T item) {
var enqueuePosition = Interlocked.Increment(ref tailIndex);
dictionary.AddOrUpdate(enqueuePosition, k => item, (k, v) => item);
}
public T Peek(long index) {
T item;
return dictionary.TryGetValue(index, out item) ?
item :
default(T);
}
public long TryDequeue(out T item) {
if (headIndex > tailIndex) {
item = default(T);
return -1;
}
var dequeuePosition = Interlocked.Increment(ref headIndex) - 1;
dictionary.TryRemove(dequeuePosition, out item);
return dequeuePosition;
}
public List<T> GetSnapshot() {
List<T> snapshot = new List<T>();
long snapshotTail = tailIndex;
long snapshotHead = headIndex;
for (long i = snapshotHead; i < snapshotTail; i++) {
T item;
if (TryDequeue(out item) >= 0) {
snapshot.Add(item);
}
}
return snapshot;
}
}