7

我刚开始使用 TPL,我想同时调用多个 Web 服务。据我所知,我看到了两种方法。

要么Parallel.ForEach

List<ServiceMemberBase> list = new List<ServiceMemberBase>(); //Take list from somewhere.
        Parallel.ForEach(list, member =>
            {
                var result = Proxy.Invoke(member);
                //...
                //Do stuff with the result
                //...
            });

或者Task<T>

List<ServiceMemberBase> list = new List<ServiceMemberBase>(); //Take list from somewhere.
        ForEach(var member in list)
        {
            Task<MemberResult>.Factory.StartNew(() => proxy.Invoke(member));
        }

        //Wait for all tasks to finish.
        //Process the result objects.

不管语法是否正确,这些是等价的吗?

它们会产生相同的结果吗?如果不是,为什么?哪个更可取?

4

3 回答 3

5

对于您讨论的代码和用例,这两种方法本质上是等效的。

当您必须将输入范围划分为多个任务(此处不适用)时,Parallel.ForEach 很有用,或者更容易同步合并多个独立并行操作的结果(可能适用于此?)。

无论如何,您已经正确地注意到,在 Parallel.ForEach 案例中,您不必手动同步等待完成,而如果您手动启动任务,则必须自己管理该同步。在这种情况下,您可能会使用类似Task.WaitAll(...).

于 2012-07-09T00:45:27.330 回答
1

如果不考虑或查看输出,我无法确定两者是否相同。但是我怀疑它们是否有那么大的不同。关于哪个更好的问题是主观的,具体取决于场景。回答哪个更可取也是非常主观的,在您提供的场景中,我会说我更喜欢 Parallel.ForEach因为我可以阅读它,但如果您的开发团队不习惯 Parallel 库,那么第二个版本就是那个去。

于 2012-07-09T01:02:23.167 回答
1

在两段代码之间,Parallel.ForEach()效率会更高,因为它Task一个接一个地处理多个项目。

但是他们都将使用尽可能多的线程ThreadPool,这在这种情况下不是一个好主意。那是因为ThreadPool如果你有非常短的、受 CPU 限制的 s,那么它擅长猜测最佳线程数Task,而这里的情况远非如此。

正因为如此,我认为最好的选择是将并行度手动限制为一个小数字(您必须测量以找出哪个数字可以提供最佳结果):

List<ServiceMemberBase> list = …; //Take list from somewhere.
Parallel.ForEach(list, new ParallelOptions { MaxDegreeOfParallelism = 10 },
member =>
{
    var result = Proxy.Invoke(member);
    //...
    //Do stuff with the result
    //...
});

如果您可以异步执行 Web 服务调用,效率会更高。这样做并同时限制并行度并不是很容易,除非您使用的是 C# 5。如果您使用的是 C# 5,并且您还更新Proxy以支持基于任务的异步模式 (TAP),您可以使用 TPL 数据流更有效地执行您的代码:

var actionBlock = new ActionBlock<ServiceMemberBase>(
    async member =>
    {
        var result = await Proxy.InvokeAsync(member);
        //...
        //Do stuff with the result
        //...
    }
    new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 10 });
于 2012-07-09T06:30:13.763 回答