C# 并行处理是一种密集的IO功能

C# 并行处理是一种密集的IO功能,c#,parallel-processing,task-parallel-library,webresponse,C#,Parallel Processing,Task Parallel Library,Webresponse,我有这个示例代码 List<Dictionary<string,string>> objects = new List<Dictionary<string,string>>(); foreach (string url in urls) { objects.add(processUrl(url)) } List objects=newlist(); foreach(url中的字符串url) { 添加(processUrl(url)) }

我有这个示例代码

List<Dictionary<string,string>> objects = new List<Dictionary<string,string>>();

foreach (string url in urls)
{
    objects.add(processUrl(url))
}
List objects=newlist();
foreach(url中的字符串url)
{
添加(processUrl(url))
}
我需要处理URL,
processUrl
下载页面并运行许多正则表达式来提取一些信息并返回一个“类似于C#JSON”的对象,所以我想并行运行,最后我需要一个对象列表,所以我需要等待所有任务继续处理,我如何才能完成这个任务?我举了很多例子,但没有一个能保存回报

首先,将重构视为

processUrl(url, objects);
并让任务负责将结果添加到列表中

然后添加锁定,这样两个并行任务就不会试图同时使用结果列表


注意:
async
在下一版本的.NET中的支持将使这变得非常简单。

像这样吗

var results = urls.AsParallel().Select(processUrl).ToList();
并行时

Parallel.ForEach(
    urls, 
    url =>
    {
        var result = processUrl(url);
        lock (syncOjbect)
            objects.Add(result);
    };


您可以使用PLinq扩展,这需要.NET 4.0

System.Threading.Tasks.Parallel
          .ForEach(urls, url => {
             var result = processUrl(url);
             lock(objects)
             {
                  objects.Add(result);
             }
           });

只要项目位于类似列表的集合中(例如数组或
列表
),就可以使用Parallel.For。然后可以使用循环索引将结果输出到数组槽中。这将是线程安全的,不需要锁。我不会在Parallel.ForEach的主体中使用锁,而是使用具有
localInit
localFinally
的重载,并在localFinally中聚合所有结果。这样,您就不会锁定每个操作,每个线程只锁定一次。在localInit中放置一个空列表,在不锁定正文的情况下添加到local,然后最终收集。所有这些选项都无法限制同时执行任务的总数。@Rick Sladkey-我不确定是否理解您的评论。这三个选项都有限制同时执行任务数量的方法,我没有在代码中说明,因为没有人问过。我只是警告大家在启动一千个线程之前要小心。@Rick Sladkey-实际上,默认情况下,这些方法都不会启动太多线程。作出线程或等待的决定是由调度程序做出的,默认情况下,它将基于CPU内核数和线程等待数。相反,若您想用这种方法启动无限数量的线程,这将是一个问题。然而,如果您使用
Task
方法,它也是可以解决的。
var tasks = urls
    .Select(url => Task.Factory.StartNew(() => processUrl(url)))
    .ToArray();

Task.WaitAll(tasks);
var restuls = tasks.Select(arg => arg.Result).ToList();
System.Threading.Tasks.Parallel
          .ForEach(urls, url => {
             var result = processUrl(url);
             lock(objects)
             {
                  objects.Add(result);
             }
           });