C# Asp.net mvc应用程序在使用Parallel.Foreach时性能下降

C# Asp.net mvc应用程序在使用Parallel.Foreach时性能下降,c#,asp.net-mvc,foreach,task-parallel-library,C#,Asp.net Mvc,Foreach,Task Parallel Library,我有一个asp.NETMVC应用程序。在应用程序启动时,我循环遍历大量数据集合,对于集合中的每个项目,我都会进行网络调用,以下载与该项目相关的一些数据 起初,我是在foreach循环中完成这项工作的,但在我的开发机器上,启动应用程序平均需要26秒。所以我决定把它放在一个parallel.ForEach循环中。当我测量执行parallel.ForEach循环与常规ForEach循环所用的时间时,我注意到,平均而言,parallel.ForEach循环的性能更好,但我的应用程序的性能显著下降,而执行

我有一个asp.NETMVC应用程序。在应用程序启动时,我循环遍历大量数据集合,对于集合中的每个项目,我都会进行网络调用,以下载与该项目相关的一些数据

起初,我是在foreach循环中完成这项工作的,但在我的开发机器上,启动应用程序平均需要26秒。所以我决定把它放在一个parallel.ForEach循环中。当我测量执行parallel.ForEach循环与常规ForEach循环所用的时间时,我注意到,平均而言,parallel.ForEach循环的性能更好,但我的应用程序的性能显著下降,而执行此操作需要5分钟的启动时间

当我在Performance Wizard中检查iis进程时,我注意到使用常规foreach循环时,iis在执行此操作时总线程数从未超过47个,但使用Parallel.foreach循环时,我的计算机上的线程数最多不超过500个

我知道,根据microsoft的Parallel.Foreach文档,对共享资源的调用将显著降低并行循环的性能

所以我的问题是:

  • 为什么它会降低这么多,是因为线程之间的上下文切换吗
  • 为什么在执行循环体时要创建这么多线程
  • 为什么并行循环的平均执行速度要比常规for循环快,但是整个应用程序在启动时的性能会下降
  • 在进行可能很慢的网络服务调用时,如何在使用或不使用并行foreach循环的情况下实现更快的应用程序启动
  • 在下面找到我正在做的代码

    //parallel loop version
    Parallel.ForEach(categories.SelectMany(c => c.Billers), service =>
    {
        try
        {
            if (service.PaymentItems == null || service.PaymentItems.Any())
            {                  
                service.PaymentItems = GetServiceOptions(service.Id);
            }
            catch (Exception ex)
            {
                _logger.Error(string.Format("Problem getting service options for {0}", service.Name), ex);
            }
    });
    
    //regular for loop version
    foreach (var service in categories.SelectMany(c => c.Billers))
    {
        try
        {
            if (service.PaymentItems == null || service.PaymentItems.Any())
                {
                    service.PaymentItems = GetServiceOptions(service.Id);
                }
            }
        catch (Exception ex)
        {
            _logger.Error(string.Format("Problem getting service options for {0}", service.Name), ex);
        }
    }
    

    GetServiceOptions方法处理网络调用

    请发布一些代码供我们查看。您可能已经做了一点:确保网络调用是异步完成的,这样它就不会阻塞线程。@BenjaminPaul请查找上面的代码。我想一个原因是您没有指定
    ParallelOptions.MaxDegreeOfParallelism
    ,因此您的机器将在默认情况下用完所有可用线程。将其限制在某个范围内可以提高速度,同时保持应用程序的性能。至少我希望如此。请发布一些代码供我们查看。您可能已经做了一点:确保网络调用是异步完成的,这样它就不会阻塞线程。@BenjaminPaul请查找上面的代码。我认为一个原因是您没有指定
    并行选项。MaxDegreeOfParallelism
    ,因此,默认情况下,您的机器将耗尽所有可用线程。将其限制在某个范围内可以提高速度,同时保持应用程序的性能。至少我希望如此。请发布一些代码供我们查看。您可能已经做了一点:确保网络调用是异步完成的,这样它就不会阻塞线程。@BenjaminPaul请查找上面的代码。我认为一个原因是您没有指定
    并行选项。MaxDegreeOfParallelism
    ,因此,默认情况下,您的机器将耗尽所有可用线程。将其限制在某个范围内可以提高速度,同时保持应用程序的性能。至少我希望如此。