首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >父任务不等待子任务

父任务不等待子任务
EN

Stack Overflow用户
提问于 2015-12-09 04:11:34
回答 2查看 166关注 0票数 2

首先,我对线程非常陌生。我想要实现的是,有一个url列表,我试图抓取它(我想),如果url有它,就会检测闪存。有些url有外部链接,这意味着我必须生成一个新任务并递归调用我的方法。我想使用AsParallel或Parallel.ForEach,但它们不接受任务输入。

所以我有两个问题。1)我想要一种更好的方法来并行地在urls中爬行(如果需要的话) 2)如果我所写的是一种很好的方法,那么我应该做什么来等待它的子任务?

我搜索了堆叠溢出,却找不到我需要的东西。如果我错过了与我相似的回答的问题,很抱歉。

代码语言:javascript
复制
    async Task CrawlAndDetectFlash(LearningResource resource, string url, int depth)
    {
        using (var client = new HttpClient())
        using (var response = await client.GetAsync(url))
        {
            response.EnsureSuccessStatusCode();
            using (var content = response.Content)
            {
                var result = content.ReadAsStringAsync().Result;
                resource.FlashRequired = result.Contains("application/x-shockwave-flash") || result.Contains("application/x-director") || result.Contains(".swf") ? 1 : 0;
                if (resource.FlashRequired == 0 && depth == 1)
                {
                    var document = new HtmlDocument();
                    document.LoadHtml(result);
                    var links = document.DocumentNode.Descendants("a")
                        .Where(a => a.Attributes.Contains("class") && String.Equals(a.GetAttributeValue("class", string.Empty), "external"))
                        .Select(a => a.GetAttributeValue("href", null))
                        .Distinct()
                        .Where(u => !String.IsNullOrEmpty(u))
                        .ToList();
                    if (links.Count > 0)
                    {
                        foreach (var link in links)
                        {
                            Task child = CrawlAndDetectFlash(resource, link, 2);
                            child.Wait();
                        }
                    }
                }
            }
        }
    }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-12-09 13:34:32

首先,您需要区分“并发”、“并行”和“异步”。并发一次做不止一件事情;并行是一种使用多个线程的并发形式;异步是一种没有线程的并发形式。当您想要在多个CPU内核上扩展线程时,并行性是CPU绑定代码的最佳选择。当您不想阻止线程时,异步是I/O绑定代码的最佳选择。

在您的例子中,看起来您主要是受I/O约束的,所以异步是可行的方法。这意味着AsParallelParallel.ForEach是这个问题的不适当解决方案(它们是并行的,而不是异步的)。

下一课(正如我在博客中描述的)是,您的不想阻止异步代码;阻塞击败了整个异步点。因此,不应使用Task<T>.ResultTask.Wait。而不是这些,只需使用await

代码语言:javascript
复制
async Task CrawlAndDetectFlashAsync(LearningResource resource, string url, int depth)
{
  using (var client = new HttpClient())
  using (var response = await client.GetAsync(url))
  {
    response.EnsureSuccessStatusCode();
    using (var content = response.Content)
    {
      var result = await content.ReadAsStringAsync(); // Result -> await
      resource.FlashRequired = result.Contains("application/x-shockwave-flash") || result.Contains("application/x-director") || result.Contains(".swf") ? 1 : 0;
      if (resource.FlashRequired == 0 && depth == 1)
      {
        var document = new HtmlDocument();
        document.LoadHtml(result);
        var links = document.DocumentNode.Descendants("a")
                    .Where(a => a.Attributes.Contains("class") && String.Equals(a.GetAttributeValue("class", string.Empty), "external"))
                    .Select(a => a.GetAttributeValue("href", null))
                    .Distinct()
                    .Where(u => !String.IsNullOrEmpty(u))
                    .ToList();
        if (links.Count > 0)
        {
          foreach (var link in links)
          {
            Task child = CrawlAndDetectFlashAsync(resource, link, 2);
            await child; // Wait -> await
          }
        }
      }
    }
  }
}

既然该方法是正确异步的,那么就可以考虑添加更多的并发性。例如,如果您希望并发处理所有子链接,则可以将foreach循环重写为:

代码语言:javascript
复制
if (links.Count > 0)
{
  var childTasks = links.Select(x => CrawlAndDetectFlashAsync(resource, x, 2)).ToList();
  await Task.WhenAll(childTasks);
}
票数 3
EN

Stack Overflow用户

发布于 2015-12-09 04:23:10

您可以这样修改代码

代码语言:javascript
复制
List<Task> children = new List<Task>();
foreach (var link in links)
{
    Task child = CrawlAndDetectFlash(resource, link, 2);
    children.Add(child);
}

Task.WaitAll(children.ToArray());
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34170575

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档