【发布时间】:2020-02-28 10:47:59
【问题描述】:
认为我给出的标题有点令人困惑,但很难表达我想要问的内容。
基本上,我正在使用 .NET 用 C# 编写一个程序,该程序使用 Google 云 API 来上传数据。
我试图以一种有效的方式做到这一点,并且成功地使用了 parallel.foreach,但我需要更好的控制。我将要上传的文件收集到一个列表中,我想按文件大小对其进行排序,然后分成 3 个相同大小(以千兆字节而不是文件数计)的列表。
其中一个列表将包含总上传大小的三分之一,但包含最大的文件(以 GB 为单位)但因此文件数最少,下一个列表将与第一个列表的总 GB 相同但由更多的小文件组成,最后一个列表将由许多小文件组成,但总大小也应与其他子列表相同。
然后我想为上传过程分配一组线程。 (例如,我希望最大的文件列表分配 5 个线程,中间分配 3 个线程,小文件列表只有 2 个线程。)是否可以将这 3 个列表设置为并行迭代,同时控制如何分配了很多线程?
这样做的最佳方法是什么?
【问题讨论】:
-
拆分成这 3 个列表,然后在每个列表上运行 Parallel.ForEach,使用 MaxDegreeOfParallellism 设置为它们指定不同的并发限制。请参阅stackoverflow.com/questions/9290498/… 了解更多信息。
-
Parallel.ForEach用于数据并行 - 通过将大量 本地 数据划分为与内核一样多的批次,并为每个 pertition 使用单独的工作任务。看起来您所做的是并发处理多个文件,这是完全不同的事情。而files to be uploaded那是异步处理,async/await做什么。再次,不同的事情。 -
我建议使用像 ActionBlock<T> 和 TransformBlock<T> 这样的 DataFlow 块将处理分解为一个具体步骤的管道,这些步骤可以有自己的 DOP,根据需要有自己的代码。对于IO任务,可以使用
asyncworker方法,使用DOP设置控制并发上传数。 -
对于数据处理,可以将DOP设置为例如1,并在worker中使用
PLINQ或Parallel.ForEach处理数据(有自己的DOP限制,否则other 块将无法运行)。或者您也可以将数据处理任务分解为单独的操作。 -
我还有一堆比较大的文件要下载、解析和导入数据库。我使用一个异步下载文件的块、一个使用有限的 DOP同步 解析它们的第二个块以及使用 SqlBulkCopy 将它们导入数据库的最后一个块来做到这一点。这样我就可以同时下载、解析和导入。
标签: c# .net multithreading parallel-processing