在 Stackoverflow 上看到了一个提问,关于并行的 WebClient,觉得回答者的代码很有参考性,下面记录一下,以便日后用到:

提问者:

我有一个功能基本上分为两个子功能。

html=RetriveHTML(int index);
returnColection = RegexProcess(html, index);

通过优化RetrieveHTML并列化来加速此过程的最佳方法是什么?

通常我用最多20000个索引来调用它。第一个subfuntcion是网络相关的(使用webclient.downloadstring从一个服务器获取几个URL HTML),第二个子功能主要是CPU。

我迷失在并行foreach和Tasks(继续,继续,fromasync)世界,我遇到麻烦来解决问题。我首先尝试使用Parallel foreach,但是我发现其性能即网络I / O在连续调用时会降级(第一个循环很快,其他循环变慢)。解决方案将释放html对象,因为它们很多很大。我正在使用.net 4.0

回答者:

    class Program
{
static void Main(string[] args)
{
ProcessInParallell();
} private static Regex _regex = new Regex("net"); private static void ProcessInParallell()
{
Uri[] resourceUri = new Uri[] { new Uri("http://www.microsoft.com"), new Uri("http://www.google.com"), new Uri("http://www.amazon.com") };
//1. Stage 1: Download HTML
//Use the blocking collection for concurrent tasks
BlockingCollection<string> htmlDataList = new BlockingCollection<string>();
Parallel.For(, resourceUri.Length, index =>
{
var html = RetrieveHTML(resourceUri[index]);
htmlDataList.TryAdd(html); //If we reach to the last index, signal the completion
if (index == (resourceUri.Length - ))
{
htmlDataList.CompleteAdding();
}
}); //2. Get matches
//This concurrent bags will be used to store the result of the matching stage
ConcurrentBag<string> matchedHtml = new ConcurrentBag<string>(); IList<Task> processingTasks = new List<Task>(); //Enumerate through each downloaded HTML document
foreach (var html in htmlDataList.GetConsumingEnumerable())
{
//Create a new task to match the downloaded HTML
var task = Task.Factory.StartNew((data) =>
{
var downloadedHtml = data as string;
if (downloadedHtml == null)
return;
if (_regex.IsMatch(downloadedHtml))
{
matchedHtml.Add(downloadedHtml);
}
},html);
//Add the task to the waiting list
processingTasks.Add(task);
} //wait for the all tasks to complete
Task.WaitAll(processingTasks.ToArray()); foreach (var html in matchedHtml)
{
//Do something with the matched result }
} private static string RetrieveHTML(Uri uri)
{
using (WebClient webClient = new WebClient())
{
//set this to null if there is no proxy
webClient.Proxy = null; byte[] data = webClient.DownloadData(uri); return Encoding.UTF8.GetString(data);
}
}
}

追问:

谢谢你的收获。但如果下载了很多/很长的html文件,这不会占用太多内存吗? -  husvar 2013年 1月23日21:58
 

回答:

我意识到如果下载的内容很大,就会占用大量内存。因此,您最好将工作量加大。干杯 -  Toan Nguyen 2013年1月23日22:45
 

谢谢浏览!

并行 Webclient(一)的更多相关文章

  1. .NET 实现并行的几种方式(三)

    本随笔续接:.NET 实现并行的几种方式(二) 在前两篇随笔中,先后介绍了 Thread .ThreadPool .IAsyncResult (即 APM系列) .Task .TPL (Task Pa ...

  2. C#的变迁史 - C# 5.0 之并行编程总结篇

    C# 5.0 搭载于.NET 4.5和VS2012之上. 同步操作既简单又方便,我们平时都用它.但是对于某些情况,使用同步代码会严重影响程序的可响应性,通常来说就是影响程序性能.这些情况下,我们通常是 ...

  3. 《C#并行编程高级教程》第9章 异步编程模型 笔记

    这个章节我个人感觉意义不大,使用现有的APM(异步编程模型)和EAP(基于时间的异步模型)就很够用了,针对WPF和WinForm其实还有一些专门用于UI更新的类. 但是出于完整性,还是将一下怎么使用. ...

  4. F# 天生就是就异步和并行的料

    做模型开发免不了要使用异步和并行计算,尤其在多核CPU的今天,更是如此,F#恰逢其时,天生就具备这种能力,先看一个例子. open System open System.Drawing open Sy ...

  5. Silverlight并行下载与串行下载

    思路清晰后仅仅只需百来行代码便可轻松编写出一套完整的资源动态下载组件- SerialDownloader和ParallelDownloader,它们共用一个完成资源表,且串行下载集成了优先机制(Dow ...

  6. 数据流(任务并行库 TPL)

    TPL 数据流库向具有高吞吐量和低滞后时间的占用大量 CPU 和 I/O 操作的应用程序的并行化和消息传递提供了基础. 它还能显式控制缓存数据的方式以及在系统中移动的方式. 为了更好地了解数据流编程模 ...

  7. 第九节:深究并行编程Parallel类中的三大方法 (For、ForEach、Invoke)和几大编程模型(SPM、APM、EAP、TAP)

    一. 并行编程 1. 区分串行编程和串行编程 ①. 串行编程:所谓的串行编程就是单线程的作用下,按顺序执行.(典型代表for循环 下面例子从1-100按顺序执行) ②. 并行编程:充分利用多核cpu的 ...

  8. .NET 并行编程——任务并行

    本文内容 并行编程 任务并行 隐式创建和运行任务 显式创建和运行任务 任务 ID 任务创建选项 创建任务延续 创建分离的子任务 创建子任务 等待任务完成 组合任务 任务中的异常处理 取消任务 Task ...

  9. C#中的多线程 - 并行编程 z

    原文:http://www.albahari.com/threading/part5.aspx 专题:C#中的多线程 1并行编程Permalink 在这一部分,我们讨论 Framework 4.0 加 ...

随机推荐

  1. JPA笔记2 OneToMany

    package one_to_many; import java.util.HashSet; import java.util.Set; import javax.persistence.Cascad ...

  2. 三.基础部分+asp网站搭建

    渗透测试流程:更全面地找出服务器的问题,更倾向保护 明确目标-->信息收集-->漏洞探测-->漏洞验证-->信息分析-->获取所需-->信息整理-->形成报告 ...

  3. 简单使用:spring boot整合spring Data JPA

    JPA顾名思义就是Java Persistence API的意思,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. 1.jpa具有什么优势? (1).标准 ...

  4. 【DB_MySQL】MySQL日志分析

    MySQL数据库常见的日志有:错误日志(log_error).慢查询日志(slow_query_log).二进制日志(bin_log).通用日志(general_log) 开启慢查询日志并分析 开启慢 ...

  5. 【Spring Boot】Spring Boot之使用ImportBeanDefinitionRegistrar类实现动态注册Bean

    一.ImportBeanDefinitionRegistrar类介绍 ImportBeanDefinitionRegistrar类通过其他@Configuration类通过@Import的方式来加载, ...

  6. [Go] golang的MPG调度模型

    MPG模式运行状态11)当前程序有三个M,如果三个M都在一个cpu运行,就是并发,如果在不同的cpu运行就是并行2)M1,M2,M3正在执行一个G,M1的协程队列有三个,M2的协程队列有三个,M3的协 ...

  7. 深入解读Linux进程调度Schedule【转】

    转自:https://blog.csdn.net/Vince_/article/details/88982802 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文 ...

  8. flask 基础2

    一.装饰器的坑 在使用装饰器函数时候,当一个装饰器装饰多个函数的时候,会由于内存地址相同时发生报错,因为装饰的都是一个函数 所以就需要引入 import functools  重新定义每一个函数的名称 ...

  9. Debian 9 部分快捷键失效问题

    教程 具体修复过程: 安装gnome-screensaver包,重启恢复正常.

  10. stringstream字符串流的妙用

    现在有一个数组,其值为从1到10000的连续增长的数字.出于某次偶然操作,导致这个数组中丢失了某三个元素,同时顺序被打乱,现在需要你用最快的方法找出丢失的这三个元素,并且将这三个元素根据从小到大重新拼 ...