【问题标题】:Clearing Thread Safe Collections while in parallel.foreach loop after insert to sql插入到 sql 后,在 parallel.foreach 循环中清除线程安全集合
【发布时间】:2017-06-03 22:04:27
【问题描述】:

我有一个使用 parallel.foreach 循环的长时间运行的进程。在该循环中,我正在根据传递的内容创建两个不同类的实例,执行次要任务,然后添加到线程安全集合中。完成后,需要将所有数据插入到 sql 中。

我遇到的问题是完成的工作量太大而无法保存在集合中,直到所有处理完成。我必须偶尔将保留的内容推送到 SQL,然后从集合中删除推送的内容,以便可以继续进行更多处理而不会耗尽内存,我不知道最好的方法。如果它不是多线程的,我可以通过检查集合的计数轻松做到这一点,如果它超过一定数量,调用一个函数,该函数将通过批量插入或值表将内容推送到 SQL,然后清除该集合在下一个声明中。在parallel.foreach 中完成此任务的最佳方法是什么?

我愿意使用任何线程安全的集合。到目前为止,我一直在使用ConcurrentQueue 并考虑切换到BlockingCollection,因为我没有看到清除并发队列的方法。我不在乎插入内容的顺序,但我确实需要能够至少删除推送到 sql 的内容。

我最好的解决方案是使用BlockingCollection.GetConsumingEnumerable()。这样,一旦超过 x 数量,我可以将该集合的内容复制到另一个线程安全集合,执行我的插入,然后使用该列表使用 BlockingCollection.GetConsumingEnumerable() 从原始列表中删除。完成后,处理临时列表。我只是认为有一种更好的方法,因为如果我必须一次迭代一个来删除,这有点违背了让它多线程的目的。

我已经看到使用了pulse and wait,但我找不到一个看起来安全的好用例。在我测试集合超过一定数量并在将其插入 sql 之前被清除后,我可能会遇到一些问题。

我正在使用 4.5 框架,我正在管理两个需要推送但不一定同时推送的不同集合。

【问题讨论】:

  • 看看TPL Dataflow。它包含协调程序中的生产者/消费者流程所需的所有构建块,在我看来,它非常适合您所描述的问题。绕道而行,看看它提供了什么。你不会后悔的。

标签: c# parallel-processing thread-safety parallel.foreach


【解决方案1】:

我不建议清除并发集合。相反,我会用新的“替换”它 - 并处理旧的内容,而其他线程将其内容推送到新的。

Interlocked.Exchange 是我用来完成此任务的技术。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 2014-11-29
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-10
    • 1970-01-01
    相关资源
    最近更新 更多