Task并行处理对象
本文关键字:并行处理 对象 Task | 更新日期: 2023-09-27 18:17:40
我正在从原始URL开始抓取网页,并递归地跟踪任何链接,以确定这些页面上列出的电子邮件地址。我使用了VS2015和。net 4.6来利用线程提供的抽象/简单任务。
我有页面下载递归工作,但应用程序仍然有一个严重的瓶颈,似乎。使用下面的简单代码,如何使流程更能够并行处理每个网页,以询问电子邮件和后续url链接的内容?
似乎任务可以串联启动,以便在页面上找到的所有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;
}
核心问题可能是您受到远程服务器的限制,而您无法控制远程服务器。你也有可能受到。net中(旧的)默认连接限制的限制;尝试在进程开始时将ServicePointManager.DefaultConnectionLimit
设置为int.MaxValue
。除此之外,你能做的就不多了。
既然你在学习async
,你应该知道最好避免async void
。理想情况下,getWEbData
应该返回Task
,这个更改允许您将"子"url视为"子"任务。这对于正确传播错误尤其有用:
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);
}