我有一个有效的网络服务,负载联系不同的网站,并从中抓取相关信息。随着需求的增长,httpwebrequests的数量也在增加。
现在我没有在Web服务中使用任何异步请求 - 这意味着ASP.net一次呈现一个请求。这显然成了一个负担,因为对Web服务本身的一个请求可能需要2分钟才能完成。
有没有办法将webservice中的所有httpwebreqeusts转换为多线程?
实现这一目标的最佳方式是什么?
谢谢!
答案 0 :(得分:0)
如果您正在使用.Net V4 +,您可以使用并行库或任务库来轻松执行此类操作。
如果您使用相同的方式调用所有Web服务(假设所有Web服务都遵循相同的WSDL,只是不同的URL,您可以使用类似的东西):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
namespace ConsoleApplication2
{
class Program
{
private const string StartUrl = @"http://blog.hand-net.com";
private static void Main()
{
var content = DownloadAsString(StartUrl);
// The "AsParallel" here is the key
var result = ExtractUrls(content).AsParallel().Select(
link =>
{
Console.WriteLine("... Fetching {0} started", link);
var req = WebRequest.CreateDefault(new Uri(link));
var resp = req.GetResponse();
var info = new { Link = link, Size = resp.ContentLength};
resp.Close();
return info;
}
);
foreach (var linkInfo in result)
{
Console.WriteLine("Link : {0}", linkInfo.Link);
Console.WriteLine("Size : {0}", linkInfo.Size);
}
}
private static string DownloadAsString(string url)
{
using (var wc = new WebClient())
{
return wc.DownloadString(url);
}
}
private static IEnumerable<string> ExtractUrls(string content)
{
var regEx = new Regex(@"<a\s+href=""(?<url>.*?)""");
var matches = regEx.Matches(content);
return matches.Cast<Match>().Select(m => m.Groups["url"].Value);
}
}
}
这个小程序首先下载一个html页面,然后提取所有href。这会生成一组远程文件。 这里的AsParralel允许以并行方式运行select的内容。
此代码没有错误处理,取消功能,但说明了AsParallel方法。
如果您无法以相同的方式呼叫所有的网络服务,您也可以使用以下内容:
Task.WaitAll(
Task.Factory.StartNew(()=>GetDataFromWebServiceA()),
Task.Factory.StartNew(()=>GetDataFromWebServiceB()),
Task.Factory.StartNew(()=>GetDataFromWebServiceC()),
Task.Factory.StartNew(()=>GetDataFromWebServiceD()),
);
此代码将添加4个任务,这些任务将在“可能的时候”运行。 WaitAll方法将在返回之前等待所有任务完成。
在可能的情况下,我的意思是线程池中的一个插槽是空闲的。使用任务库时,默认情况下每个处理器核心有一个线程池。如果您有100个任务,则4个核心计算机上的4个工作线程将处理100个任务。