c# - AsParallel() 顺序执行

标签 c# .net linq task-parallel-library plinq

我有以下 PLINQ 查询:

// Let's get a few customers
List<Customer> customers = CustomerRepository.GetSomeCustomers();

// Let's get all of the items for all of these customers
List<CustomerItem> items = customers
    .AsParallel()
    .SelectMany(x => ItemRepository.GetItemsByCustomer(x))
    .ToList();

我希望 GetItemsByCustomer() 为每个客户并行执行,但它按顺序运行

我已经尝试过强制并行,但仍然没有成功:

List<CustomerItem> items = customers
    .AsParallel()
    .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
    .SelectMany(x => ItemRepository.GetItemsByCustomer(x))
    .ToList();

方法签名:

private IEnumerable<Item> GetItemsByCustomer(Customer customer)
{
    // Get all items for a customer...
}

根据 this article ,如果 PLINQ 认为合适,当然可以采用顺序路线,但强制并行性仍应覆盖这一点。

注意:上面的示例纯粹是说明性的 - 假设 customers 是一个小列表,GetItemsByCustomer 是一个昂贵的方法。

最佳答案

AsParallel() 没有任何问题。如果可能,它将并行运行,并且您的 LINQ 表达式中没有顺序依赖性,因此没有任何强制它顺序运行的东西。

您的代码不能并行运行的几个原因可能是:

  1. 您的 box/vm 有一个 CPU,或者您有一个 .NET 设置来将并行度限制为一个 CPU。您可以使用以下代码模拟它:

          var customers = new List<Customer>() { new Customer() {Name = "Mick", Surname = "Jagger"}, new Customer() {Name = "George", Surname = "Clooney"},new Customer() {Name = "Kirk", Surname = "DOuglas"}};
    
          var items = customers
            .AsParallel()
            .SelectMany(x =>
            {
                 Console.WriteLine("Requesting: " + x.Name + " - " + DateTime.Now);
                 Thread.Sleep(3000);
                 return new List<CustomerItem>();
    
            })
            .WithDegreeOfParallelism(1)
            .ToList();
    

    即使您在单个核心/CPU 盒上或当并行度为 1 时使用 WithExecutionMode(ParallelExecutionMode.ForceParallelism) 强制并行化,您的设置也不会生效,因为真正的并行化不是可能。

  2. 您的存储库中的共享资源发生了一些线程锁定。您可以使用以下代码模拟线程锁定:

        var customers = new List<Customer>() { new Customer() {Name = "Mick", Surname = "Jagger"}, new Customer() {Name = "George", Surname = "Clooney"},new Customer() {Name = "Kirk", Surname = "DOuglas"}};
    
        var locker = new object();
    
        // Let's get all of the items for all of these customers
        var items = customers
            .AsParallel()
            .SelectMany(x =>
            {
                lock (locker)
                {
                    Console.WriteLine("Requesting: " + x.Name + " - " + DateTime.Now);
                    Thread.Sleep(3000);
                    return new List<CustomerItem>();
                }
    
            })
            .ToList();
    
  3. 某些数据库设置强制查询/读取在某些情况下按顺序进行,这可能会给您一种印象,即您的 C# 代码没有并行运行,而实际上是这样。

关于c# - AsParallel() 顺序执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26210892/

相关文章:

c# - 调用 BeginSaveChanges(null, null) 来执行“即发即忘”异步 DataContext 调用是否安全?

c# - 使用存储过程检索数据

c# - 从 C# 调用 FORTRAN DLL 的 protected 内存冲突

.net - GraphSharp .Net 图形布局引擎

linq - Sitecore7 Linq to Sitecore 仅适用于 SearchResultItem 而不适用于自定义映射类

c# - 如何让一个类的多个实例(在不同的线程中)监听同一个事件?

c# - 选择语句执行 "for each"操作,然后返回自身

.net - 文件夹重定向处于事件状态时解析 'Environment.SpecialFolder.Personal'

c# - 在 include 内使用 where 子句生成错误 "The Include path expression must refer to a navigation property defined on the type"

c# - 使用 LINQ where(lamdaexp).First 和 First(lambdaexp)