我正在抓取以原始网址开头的网页,并以递归方式跟踪任何链接,以确定这些网页上列出的电子邮件地址。我使用VS2015和.net 4.6来利用线程提供的抽象/简单任务。
我的页面下载递归工作,但似乎应用程序仍然存在严重的瓶颈。使用下面的简单代码,如何使流程更能够并行处理每个网页以查询电子邮件和后续网址链接的内容?
似乎任务可以串联启动,以便在页面上找到的所有URL可以同时添加到循环逻辑的下一次迭代中?或者现在可以在引擎盖下处理这个任务吗?
下面是我的代码,请提供一些解释,以便我能够更好地理解解决方案,因为我刚开始执行任务。 (代码正在使用HTML敏捷包)
List<PageEmail> lstEmailData = new List<PageEmail>();
private void startButton_Click(object sender, RoutedEventArgs e)
{
getWEbData("http://localhost:801/"); //starting url
}
private async void getWEbData(string url) {
Task<string> getHTMLTask = AccessTheWebAsync(url);
string PageData = await getHTMLTask;
var html = new HtmlDocument();
html.LoadHtml (PageData);
var emails = html.DocumentNode.SelectNodes("//a[@href]")
.Select(a => a.Attributes["href"].Value)
.Where(href => href.StartsWith("mailto:")) // keep emails, skipp links
.ToList();
lstEmailData.Add(new PageEmail(url, emails));
var urls = html.DocumentNode.SelectNodes("//a[@href]")
.Select(a => a.Attributes["href"].Value)
.Where(href => !href.StartsWith("mailto:")) // skip emails, find only url links
.ToList();
foreach (string s in urls) {
getWEbData(s);
}
}
async Task<string> AccessTheWebAsync(string URL)
{
HttpClient client = new HttpClient() { MaxResponseContentBufferSize = 1000000 };
Task<string> getStringTask = client.GetStringAsync(URL);
return await getStringTask;
}
答案 0 :(得分:2)
核心问题可能是您受到无法控制的远程服务器的限制。您也可能受到.NET中(旧的)默认连接限制的限制;尝试在流程开始时将ServicePointManager.DefaultConnectionLimit
设置为int.MaxValue
。除此之外,你做的并不多。
由于您正在学习async
,因此您应该知道避免async void
是最好的。理想情况下,getWEbData
应返回Task
,此更改可让您对待孩子&#34;网址为&#34; child&#34;任务。这对于正确传播错误特别有用:
private async void startButton_Click(object sender, RoutedEventArgs e)
{
await GetWebDataAsync("http://localhost:801/"); //starting url
}
private async Task GetWebDataAsync(string url) {
var urls = ...;
var urlTasks = urls.Select(s => GetWebDataAsync(s));
await Task.WhenAll(urlTasks);
}