【问题标题】:Hanging HtmlAgilityPack Task挂起 HtmlAgilityPack 任务
【发布时间】:2020-01-01 01:29:28
【问题描述】:

我正在尝试使用 HtmlAgilityPack 解析 html 页面以从中提取链接,然后将链接添加到 ListBox,然后将链接从 listBox 添加到队列。
我有三个任务(PageParse、AddItemsToList、EnqueueFromList)
好的我的问题是当我单击按钮时整个应用程序都挂起。
按钮代码

private void CrawdBtn_Click(object sender, EventArgs e)
    {
        t = Task.Factory.StartNew(PageParse);
        t.Wait();
        TaskAddToList = Task.Factory.StartNew(() => AddItemsToList(t.Result));
        TaskAddToList.Wait();

        b = new Task(EnqueueFromList);
        b.Start();
        //Task.WaitAll(t,b);
        CrawdBtn.Enabled = true;

    }

页面解析方法

public HtmlAgilityPack.HtmlDocument PageParse()
    {
        MessageBox.Show($"Page Parse Has started");

        web = new HtmlWeb();
        doc = new HtmlAgilityPack.HtmlDocument();
        doc = web.Load(UrlText.Text);



        return doc;
    }


将项目添加到列表代码

private void AddItemsToList(HtmlAgilityPack.HtmlDocument doc)
    {
        foreach (HtmlNode Node in doc.DocumentNode.SelectNodes("//a[@href]"))
        {
            HtmlAttribute att = Node.Attributes["href"];
            listBox1.Invoke(new AddToListDelegate(AddToList), att.Value);
            Thread.Sleep(1000);
        }
    }

我通过以下断点注意到调试器在执行 PageParse 方法时挂起

【问题讨论】:

  • Wait() 使整个过程同步。 (顺便说一句,为什么TaskFactory.StartNew() 而不是Task.Run()?)。您需要将事件处理程序设为async,然后当方法的本机异步版本不可用时,您可以使用Task.Run() 调用异步方法。例如,将此添加到您的 Button.Click 异步处理程序:var doc = await GetDocumentAsync(url); 并添加这两个方法:internal HtmlAgilityPack.HtmlDocument GetDocument(string url) => new HtmlWeb().Load(url);internal Task<HtmlAgilityPack.HtmlDocument> GetDocumentAsync(string url) => Task.Run(() => GetDocument(url));
  • 当然,您可以将这些任务添加到List<Task<HtmlAgilityPack.HtmlDocument>>,然后再添加到var docs = await Task.WhenAll([Your List Of Tasks]);docs 将包含所有 HtmlDocument 对象。或者修改 async/sync 方法以返回已经详细说明的字符串列表/HtmlElements/whatever。

标签: c# winforms web-crawler task html-agility-pack


【解决方案1】:

如果您对使用异步方法感兴趣,请像这样以异步方式使用PageParse

    public static async Task<HtmlDocument> PageParse(String url)
    {
        return await new HtmlWeb().LoadFromWebAsync(url);
    }

您还可以使用 Linq 获取所有 href 值的列表,然后将 / AddRange 分配给 AddToList。这将防止从站点返回的“每个”URL 延迟 1 秒。

t.Result.DocumentNode.SelectNodes("//a[@href]").Select(x => x.Attributes["href"].Value).ToList();

我不确定第三个任务是做什么的,但建议用上述方法测试这两个任务,看看它是否能解决你的挂起问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-10
    • 2019-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-22
    相关资源
    最近更新 更多