在并行插入到SQL

时间:2017-06-03 22:04:28

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

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

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

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

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

我已经看到使用了pulse and wait,但我找不到一个看似安全的好用例。在我测试集合超过一定数量并在将其插入sql之前清除之后,我可以得到一些东西。

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

1 个答案:

答案 0 :(得分:1)

我不建议清除并发收集。相反,我会替换'它有一个新的 - 并处理旧的内容,而其他线程将其内容推送到新的内容。

Interlocked.Exchange是我用来实现这一目标的技术。