并发集合和独特元素
我有一个包含重复元素的并发 BlockingCollection
。如何修改它以添加或获取不同的元素?
I have a concurrent BlockingCollection
with repeated elements. How can modify it to add or get distinct elements?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
BlockingCollection
的默认后备存储是ConcurrentQueue
。正如其他人指出的那样,使用它来添加不同的项目相当困难。不过,您可以创建自己的实现
IProducerConsumerCollection
的集合类型,并将其传递给BlockingCollection
构造函数。想象一个 ConcurrentDictionary,其中包含当前队列中项目的键。要添加项目,请首先在字典上调用
TryAdd
,如果该项目不在字典中,则将其添加,并将其添加到队列中。Take
(和TryTake
)从队列中获取下一个项目,将其从字典中删除,然后返回。我希望有一个并发的
HashTable
,但由于没有并发的,所以您必须使用ConcurrentDictionary
。The default backing store for
BlockingCollection
is aConcurrentQueue
. As somebody else pointed out, it's rather difficult to add distinct items using that.However, you could create your own collection type that implements
IProducerConsumerCollection
, and pass that to theBlockingCollection
constructor.Imagine a
ConcurrentDictionary
that contains the keys of the items that are currently in the queue. To add an item, you callTryAdd
on the dictionary first, and if the item isn't in the dictionary you add it, and also add it to the queue.Take
(andTryTake
) get the next item from the queue, remove it from the dictionary, and return.I'd prefer if there was a concurrent
HashTable
, but since there isn't one, you'll have to do withConcurrentDictionary
.这是
IProducerConsumerCollection< 的实现;T>
具有队列行为的集合,也拒绝重复的项目:使用示例:
警告:调用如果项目重复,
queue.TryAdd(item);
不会出现返回false
的预期行为。任何添加重复项的尝试都必然会导致DuplicateKeyException
。不要尝试通过返回false
来“修复”上述ConcurrentQueueNoDuplicates.TryAdd
实现或TryTake
。BlockingCollection
将通过抛出不同的异常 (
InvalidOperationException
) 做出反应,并且最重要的是其内部状态将被损坏。目前(.NET 7)一个错误,该错误会将BlockingCollection
的有效容量减少 1,其底层存储具有TryAdd
实现,该实现返回false
。该错误已修复< /a> 对于 .NET 8,这将防止损坏,但不会改变错误抛出行为。Here is an implementation of a
IProducerConsumerCollection<T>
collection with the behavior of a queue, that also rejects duplicate items:Usage example:
Caution: Calling
queue.TryAdd(item);
is not having the expected behavior of returningfalse
if the item is a duplicate. Any attempt to add a duplicate item results invariably in aDuplicateKeyException
. Do not attempt to "fix" the aboveConcurrentQueueNoDuplicates<T>.TryAdd
implementation, or theTryTake
, by returningfalse
. TheBlockingCollection<T>
will react by throwing a different exception (InvalidOperationException
), and on top of that its internal state will become corrupted. There is currently (.NET 7) a bug that reduces by one the effective capacity of aBlockingCollection<T>
whose underlying storage has aTryAdd
implementation that returnsfalse
. The bug has been fixed for .NET 8, which will prevent the corruption, but it won't change the error-throwing behavior.