2015-02-11 70 views
1

我试图学习如何使用线程和Im坚持并发集合。并发收集VS锁定列表

我有应用程序,其中有对象和方法的列表unfinishedOBjectsList<MyObject>,对特定对象(如DoChange(MyObject对象))做了一些更改。之后,该对象从第一个列表中取出并插入finishedObjectsList<MyObject>

现在,我想运行使用线程的方法,该线程工作正常 - 每个线程都做了一些更改(更改次数较少,所以我添加了ThreadSleep()来模拟一些对象的更长处理) unfinishedOBjectsList,将它从unfinishedOBjectsList中移除并放入第二个列表中。

下一步我想实现的是,会有另一种方法(例如用户使用按钮处理),这将允许用户从第一个列表中选择任何对象并将其删除为manualy。我想模拟的“问题”是,如果对象正在被线程“处理”,用户不应该能够从列表中删除它。

我试过ConcurrentQueue - 但问题是,使用队列,我无法删除特定的对象(使用类似Remove(MyObject)的东西,因为我可以做与列表)。之后,我尝试了ConcurrentBag和BlockingCollection,但问题是一样的 - 我能够删除集合中的下一个对象,但不是集合中间的对象。

我曾考虑过使用字典,但我不能看到为什么我应该使用字典与键,值参数,而我只需要存储对象的原因。

我的问题是 - 我应该甚至在这种情况下使用ConcurrentCollections?或者我应该简单地锁定列表并保持原样?处理多访问列表时,正确的方法是什么?

谢谢

回答

1

队列,栈,箱包有你不需要知道哪个对象你得到,直到你得到它的好处。在你的情况下,你确实知道你想操作哪个对象。

听起来好像你有一种混合模型,你有一个处理机制,从一个集合中抓取未完成的对象,'完成'它们,然后将它们放入'已完成'集合中。 (看起来你在使用列表。)你也有一个用户界面,允许用户从'未完成'集合中选择任何给定的对象并将其从该集合中取出。

的方式您处理机制应该工作是这样的:码处理对象应

  • 删除要从“未完成”的收集处理的对象。
  • 处理对象。
  • 将它放入'已完成'集合中。
  • 重复。

也就是说,当前正在处理的对象不应出现在'未完成'集合中,因为它在处理之前已被删除。

现在,如果您想要将“未完成”集合中的项目显示给用户,则需要遍历它们。你还需要给他们一些键,所以当用户点击其中一个键时,你就可以知道哪一个键。

一个很好的方法是使用Interlocked.Increment(ref staticSerialNumber)来增加序列号。

然后,您可以使用ConcurrentDictionary<int><yourObject>集合作为“未完成”集合。

要插入一个新的对象变成很容易:

Interlocked.Increment(ref staticSerialNumber); 
dict.GetOrAdd(staticSerialNumber, newObject); 

要获得对象的列表中很容易。使用dict.GetEnumerator()方法。

要从字典中获取项目,可以使用枚举数查找第一个项目,然后使用TryRemove(key)来完成此操作。

简而言之,ConcurrentDictionary可能是您的应用程序的不错选择。

+0

这是很好的解释,我不知道有像“联锁”之类的东西。我一定会用它并按照你的建议来实现它。感谢您的时间和帮助,我真的很感激。 – JakubJ 2015-02-12 08:19:51