C# 使用Parallel.ForEach和;Task.Factory.StartNew

C# 使用Parallel.ForEach和;Task.Factory.StartNew,c#,asp.net,.net,asp.net-mvc,parallel-processing,C#,Asp.net,.net,Asp.net Mvc,Parallel Processing,我正在开发一个asp.net mvc-4 web应用程序。。但我不确定在列表上使用这两种方法进行迭代和启动WebClient()调用之间有什么区别:- 方法1 Parallel.ForEach(photos,new ParallelOptions { MaxDegreeOfParallelism = 7 }, p => { ResourceAccountListInfo resourceAccountListInfo

我正在开发一个asp.net mvc-4 web应用程序。。但我不确定在列表上使用这两种方法进行迭代和启动WebClient()调用之间有什么区别:-

方法1

Parallel.ForEach(photos,new ParallelOptions { MaxDegreeOfParallelism = 7 }, p =>
                            {
         ResourceAccountListInfo resourceAccountListInfo = new ResourceAccountListInfo();
         WebClient wc = new WebClient();               

         var json =  wc.DownloadString(p.url);
         resourceAccountListInfo = JsonConvert.DeserializeObject<ResourceAccountListInfo>(json);
         if (resourceAccountListInfo.operation.Details.CUSTOMFIELD.Count > 0)
                    {
                        List<CUSTOMFIELD> customfield = resourceAccountListInfo.operation.Details.CUSTOMFIELD.Where(a =>
                                 a.CUSTOMFIELDLABEL.ToLower() == "name"
                                ).ToList();
                        if (customfield.Count == 1)
                        {
                            PMresourcesOnly.Add(resourceAccountListInfo.operation.Details);

                        }

                    }
            //code goes here
                            });
Parallel.ForEach(照片,新的并行选项{MaxDegreeOfParallelism=7},p=>
{
ResourceAccountListInfo ResourceAccountListInfo=新的ResourceAccountListInfo();
WebClient wc=新的WebClient();
var json=wc.DownloadString(p.url);
resourceAccountListInfo=JsonConvert.DeserializeObject(json);
如果(resourceAccountListInfo.operation.Details.CUSTOMFIELD.Count>0)
{
List customfield=resourceAccountListInfo.operation.Details.customfield.Where(a=>
a、 CUSTOMFIELDLABEL.ToLower()=“名称”
).ToList();
如果(customfield.Count==1)
{
PMresourcesOnly.Add(resourceAccountListInfo.operation.Details);
}
}
//代码在这里
});
方法2

   foreach (Photo p in photos)
                        {
            Task.Factory.StartNew(() =>
                        {
            ResourceAccountListInfo resourceAccountListInfo = new ResourceAccountListInfo();
            WebClient wc = new WebClient();

            var json =  wc.DownloadString(p.url);
            resourceAccountListInfo = JsonConvert.DeserializeObject<ResourceAccountListInfo>(json);
                     if (resourceAccountListInfo.operation.Details.CUSTOMFIELD.Count > 0)
                    {
                        List<CUSTOMFIELD> customfield = resourceAccountListInfo.operation.Details.CUSTOMFIELD.Where(a =>
                                 a.CUSTOMFIELDLABEL.ToLower() == "name"
                                ).ToList();
                        if (customfield.Count == 1)
                        {
                            PMresourcesOnly.Add(resourceAccountListInfo.operation.Details);

                        }

                    }
            //code goes here
                                });
                        }
foreach(照片中的照片p)
{
Task.Factory.StartNew(()=>
{
ResourceAccountListInfo ResourceAccountListInfo=新的ResourceAccountListInfo();
WebClient wc=新的WebClient();
var json=wc.DownloadString(p.url);
resourceAccountListInfo=JsonConvert.DeserializeObject(json);
如果(resourceAccountListInfo.operation.Details.CUSTOMFIELD.Count>0)
{
List customfield=resourceAccountListInfo.operation.Details.customfield.Where(a=>
a、 CUSTOMFIELDLABEL.ToLower()=“名称”
).ToList();
如果(customfield.Count==1)
{
PMresourcesOnly.Add(resourceAccountListInfo.operation.Details);
}
}
//代码在这里
});
}

感谢并行。ForEach提供了一种在集合中迭代的便利。 尽管可以在循环中调用
Task.Factory.StartNew
,但它本身并没有任何东西表明它将在循环中使用。你可以只开始一项任务

由于
Parallel.ForEach
假定一组并行操作,因此它为您提供了
ParallelOptions
,允许您指定该循环范围内的并发操作数。这很有用,因为在某些情况下,我们可能不关心有多少并发操作,但在其他情况下,我们可能会关心。看看哪个描述了使用
信号量来限制并发任务的数量。设置
MaxDegreeOfParallelism
比使用
信号量要容易得多


另外,
Parallel.ForEach
返回一个
ParallelLoopResult
,它使您能够查看循环中的所有操作。要在一组任务中获得同样的可见性,需要做更多的工作。您还可以通过一个方法调用而不是停止多个任务来停止循环。

所有线程是否都替换
resourceAccountListInfo
?这似乎是错误的区别是:Parallel.ForEach等待所有“照片”完成,然后继续。在Task.Factory.StartNew中,无论照片是否完成,它都会继续运行。@ScottChamberlain抱歉,我只显示了与我的问题相关的部分代码。。现在,在每次迭代中,resourceAccountListInfo上都有额外的处理……最终,由您为您的代码选择您认为合适的最佳解决方案;我想总是很难确定什么是最合适的,所以你需要根据不同的解决方案如何工作来定义它,所以它需要一些尝试和错误,以及性能指标,并且必须检查哪一个是我认为最好的:)我只是想给我的两分钱@johnG有很多方法可以让代码做同样的事情,我不认为你可以概括并说Parallel.ForEach比Task更糟糕。反之亦然,除非在某些情况下……即使在那些情况下,它们也可能有相同的最终结果,所以这没什么关系。当涉及到性能时,这可能很重要。在运行任务管理器时,您应该在任务管理器中查看CPU核心的使用情况,以查看是否使用了所有的CPU可计算性。因此,您使用的是Parallel.ForEach而不是Tas.Factory.StartNew是否正确?使用Parallel.Foreach时的第二个问题在我的例子中,我是否需要显式使用lock来确保没有任何数据损坏,或者这不是必需的?如果我正在处理一个我想并行处理的集合,我会使用
Parallel.Foreach
。否则我可能会启动一个
任务
。如果并行任务在需要它的东西上运行,比如它们不能同时更新的共享属性,则需要使用某种类型的锁定(或其他管理并发性的方法)。但这种锁定更可能出现在我正在处理的对象中——编写它们以使它们支持并发性——而不是在循环本身中。你说的“否则我可能会启动任务”到底是什么意思??当我需要将锁与Parallel.forEach或与任务一起使用时?您能提供更多详细信息吗?这有点深入。我会从阅读什么时候使用锁开始。它适用于任何多线程。那么,即使我选择执行任务,我也需要使用锁吗?