我最近发现下面的代码可以有效地运行很多IO绑定的任务(参见链接)。
http://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx
我的印象如下:
这比使用parallel.foreach要好得多,因为工作不受cpu限制。
foreachasync将有助于将尽可能多的io任务排队(无需将这些任务放在单独的线程上)。
tpl将“知道”这些是基于io的任务,而不是启动更多的线程,而是使用回调/任务完成源向主线程发送信号,从而节省线程上下文切换的开销。
我的问题是,由于parallel.foreach本质上有自己的maxDegreeofparallelism定义我如何知道如何在IEnumerable扩展的示例代码中定义DOP参数?
例如,如果我有1000个项要处理,并且需要对每个项执行基于IO的SQL Server DB调用,我是否将1000指定为DOP?对于parallel.foreach,它用作一个限制器,以防止过多的线程旋转,从而可能会损害性能。但在这里,它似乎被用来划分最小数量的异步任务。我认为应该至少没有最大值(最小值是要处理的总项目),因为我想尽可能多地将基于IO的调用排队到数据库中。
我怎样才能知道该如何查看dop参数呢?
public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
{
return Task.WhenAll(
from partition in Partitioner.Create(source).GetPartitions(dop)
select Task.Run(async delegate {
using (partition)
while (partition.MoveNext())
await body(partition.Current);
}));
}
最佳答案
foreach本质上有自己的maxDegreeofparallelism
好的,Parallel.ForEach
中内置的启发式方法很容易随着时间的推移产生大量的任务(如果您的工作项有10毫秒的延迟,那么您在大约一个小时后就会得到数百个任务——我测量了它)。非常可怕的设计缺陷,不要试图模仿这一点。
当并行运行io时,无法替代经验确定正确的值。这就是为什么第三方物流在这方面如此糟糕。例如,执行顺序IO的磁盘的DOP为1。一个ssd做随机喜欢基本无限(100?)是的。
远程web服务无法让您知道正确的dop。您不仅需要测试,还需要请求所有者允许向服务发送垃圾邮件,这些请求可能会使服务过载。
我可以指定1000作为毒品吗?
那你就根本不需要这个设施了。生成所有任务,然后等待所有任务。但1000可能是错误的dop,因为它压倒了db,没有任何好处。
在这里,它似乎被用来划分最小数量的异步任务Parallel.For
的另一个可怕特性。在低CPU的机器上,它可能会产生一些小任务。可怕的API。不要与IO一起使用。(我使用AsParallel
来设置精确的dop,而不是最大dop。)
因为我想将尽可能多的基于IO的调用排队到数据库
为什么?不是个好计划。
顺便说一下,你在这里发布的方法是好的,我也使用这个。我希望是在框架内。这个精确的方法是每周大约10个SO问题的答案(“我如何异步并行处理100000个项目?”)是的。