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;
}

Task<T>并行处理对象

核心问题可能是您受到远程服务器的限制,而您无法控制远程服务器。你也有可能受到。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);
}