繁体   English   中英

AsParallel()顺序执行

[英]AsParallel() executing sequentially

我有以下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...
}

根据本文 ,如果PLINQ认为合适,当然可以采用顺序路由,但是强制并行性仍应优先于此。

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

AsParallel()没有错。 如果可能,它将以并行方式运行,并且LINQ表达式中没有顺序依赖关系,因此没有什么可以强迫它顺序运行。

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

  1. 您的机器/ 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盒上使用WithExecutionMode(ParallelExecutionMode.ForceParallelism)强制WithExecutionMode(ParallelExecutionMode.ForceParallelism) ,或者当并行度为1时,您的设置也不会生效,因为不可能进行真正的并行化。

  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#代码实际上不是并行运行的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM