随着新ConcurrentBag<T>的.NET 4,你怎么从它,只有当删除一些具体目标TryTake()和TryPeek()可用?
我想用的TryTake(),然后只是增加了生成的对象回列表,如果我不想要删除它,但我觉得我可能会失去了一些东西.这是正确的方法吗?
Mar*_*ers 83
简短的回答:你不能轻易做到这一点.
ConcurrentBag为每个线程保留一个线程本地队列,并且只有在其自己的队列变空时才查看其他线程的队列.如果您删除了一个项目并将其放回原来,那么您删除的下一个项目可能会再次成为同一个项目.无法保证重复删除项目并将其放回将允许您迭代所有项目.
两种替代方案:
Han*_*ant 15
你不能.它是一个袋子,它没有订购.当你把它放回去时,你将陷入无休止的循环中.
你想要一套.您可以使用ConcurrentDictionary模拟一个.或者是一个用锁来保护自己的HashSet.
ConcurrentBag 非常适合处理一个列表,您可以在其中添加项目并从多个线程中枚举,然后最终将其扔掉,正如它的名字所暗示的那样:)
正如 Mark Byers 所说,您可以重新构建一个新的 ConcurrentBag,其中不包含您要删除的项目,但您必须使用锁来保护它免受多线程命中。这是一个单行:
myBag = new ConcurrentBag<Entry>(myBag.Except(new[] { removedEntry }));
Run Code Online (Sandbox Code Playgroud)
这是有效的,并且符合 ConcurrentBag 的设计精神。
小智 5
马克是正确的,因为ConcurrentDictionary将以您想要的方式工作。如果您仍然希望使用ConcurrentBag,请注意,以下内容(效率不高)将帮助您实现目标。
var stringToMatch = "test";
var temp = new List<string>();
var x = new ConcurrentBag<string>();
for (int i = 0; i < 10; i++)
{
x.Add(string.Format("adding{0}", i));
}
string y;
while (!x.IsEmpty)
{
x.TryTake(out y);
if(string.Equals(y, stringToMatch, StringComparison.CurrentCultureIgnoreCase))
{
break;
}
temp.Add(y);
}
foreach (var item in temp)
{
x.Add(item);
}
Run Code Online (Sandbox Code Playgroud)