c# - 使用 'AsParallel()'/'Parallel.ForEach()' 指针?

标签 c# .net multithreading parallel-processing

寻找有关利用 AsParallel()Parallel.ForEach() 来加快速度的小建议。

请参阅下面我得到的方法(针对此示例进行了简化/混合)。

它采用类似“美国、法国、亚太地区”的列表,其中“亚太地区”是其他 50 个“美国、法国、日本、意大利、英国”等国家/地区的别名。该方法应采用“美国、法国、亚太地区”,并将其转换为“美国”、“法国”以及“亚太地区”中的所有国家/地区的列表。

private IEnumerable<string> Countries (string[] countriesAndAliases)
{
    var countries = new List<string>();

    foreach (var countryOrAlias in countriesAndAliases)
    {
        if (IsCountryNotAlias(countryOrAlias))
        {
            countries.Add(countryOrAlias);
        }
        else 
        {
            foreach (var aliasCountry in AliasCountryLists[countryOrAlias]) 
            {
                countries.Add(aliasCountry);
            }
        }
    }

    return countries.Distinct();
}

将其并行化是否像将其更改为以下内容一样简单?使用 AsParallel() 有比这更细微的差别吗?我应该使用 Parallel.ForEach() 而不是 foreach 吗?并行化 foreach 循环时应该使用哪些经验法则?

private IEnumerable<string> Countries (string[] countriesAndAliases)
{
    var countries = new List<string>();

    foreach (var countryOrAlias in countriesAndAliases.AsParallel())
    {
        if (IsCountryNotAlias(countryOrAlias))
        {
            countries.Add(countryOrAlias);
        }
        else 
        {
            foreach (var aliasCountry in AliasCountryLists[countryOrAlias].AsParallel()) 
            {
                countries.Add(aliasCountry);
            }
        }
    }

    return countries.Distinct();
}

最佳答案

几点。

只写 countriesAndAliases.AsParallel()没用。 AsParallel()使并行执行后出现的 Linq 查询的一部分。部分是空的,所以根本没有用。

通常你应该更换foreachParallel.ForEach() .但要注意非线程安全的代码!你拥有了它。你不能把它包装成 foreach因为List<T>.Add本身不是线程安全的。

所以你应该这样做(抱歉,我没有测试,但它可以编译):

        return countriesAndAliases
            .AsParallel()
            .SelectMany(s => 
                IsCountryNotAlias(s)
                    ? Enumerable.Repeat(s,1)
                    : AliasCountryLists[s]
                ).Distinct();

编辑:

你必须确定另外两件事:

  1. IsCountryNotAlias必须是线程安全的。如果是pure function就更好了.
  2. 没有人会修改AliasCountryLists同时,因为字典不是线程安全的。或者使用 ConcurrentDictionary可以肯定。

对您有帮助的有用链接:

Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4

Parallel Programming in .NET 4 Coding Guidelines

When Should I Use Parallel.ForEach? When Should I Use PLINQ?

PS:如您所见,新的并行功能并不像看起来(和感觉)那么明显。

关于c# - 使用 'AsParallel()'/'Parallel.ForEach()' 指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3780870/

相关文章:

c# - SendMessage() 仅在窗口打开时有效,在最小化时无效

c# - 运行 WPF 应用程序的可执行文件时 log4net 不工作

c# - 我需要 "transactionScope.Complete();"吗?

java - 给一个C++类foo,里面有一个synchronized方法。如何保证synchronized方法只被一个线程访问

c - PThreads上下文中的多处理器与多线程

c# - 将 PHP 正则表达式转换为 c# RegEx 模式

c# - 如何在 C# asp.net mvc3 中合并两个对象

c# - 通过命令行或 C# 创建 EF 模型

.net - 是否有像 Java 的 enum.ordinal() 这样的 .NET 构造?

c# - .NET4.0 : Thread-Safe Updating of ConcurrentDictionary<TKey, T值>