【问题标题】:Concurrent Collection vs locking list并发收集与锁定列表
【发布时间】:2015-02-11 23:12:40
【问题描述】:

我正在尝试学习如何使用线程,但我坚持使用并发集合。

我有一个应用程序,其中我列出了 unfinishedOBjectsList<MyObject> 对象和一个方法,它们对特定对象进行了一些更改(类似于 DoChange(MyObject object) )。之后,该对象从第一个列表中取出并插入finishedObjectsList<MyObject>

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

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

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

我考虑过使用字典,但我不明白为什么我应该使用带有键值参数的字典,而我只需要存储对象。

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

谢谢

【问题讨论】:

    标签: c# multithreading collections concurrency


    【解决方案1】:

    队列、堆栈和袋子的好处是在你得到它之前你不需要知道你得到的是哪个对象。在您的情况下,您确实知道要操作哪个对象。

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

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

    • 从“未完成”集合中移除要处理的对象。
    • 处理对象。
    • 将其放入“完成”集合中。
    • 重复。

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

    现在,如果您想向用户显示“未完成”集合中的项目,则需要遍历它们。您还需要为它们提供某种键,因此当用户单击其中一个时,您将能够分辨出是哪一个。

    一个很好的方法是使用序列号,您可以使用Interlocked.Increment(ref staticSerialNumber) 递增该序列号。

    然后您可以将ConcurrentDictionary<int><yourObject> 集合用于您的“未完成”集合。

    向其中插入一个新对象很容易:

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

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

    要从字典中取出一个项目,您可以使用枚举器找到第一个项目,然后使用TryRemove(key) 来做到这一点。

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

    【讨论】:

    • 这个解释的很好,以前不知道有“互锁”之类的。我一定会使用它并按照您建议的方式实施它。感谢您的时间和帮助,我真的很感激。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多