1

我正在尝试使用AngleSharp加载许多页面。这个想法是它加载一个页面,如果这个页面有到下一个的链接,加载下一个页面等等,这些方法描述如下。但我得到了内部异常:

Specified argument was out of the range of valid values.
Parameter name: index"

我相信与同步有关的东西Thread

    public static bool ContainsNextPage(IDocument document)
    {
        String href = document.QuerySelectorAll(".prevnext a")[0].GetAttribute("href");
        if (href == String.Empty)
            return false;
        else
            return true;
    }

    public static string GetNextPageUrl(IDocument document)
    {
        return document.QuerySelectorAll(".prevnext a")[0].GetAttribute("href");

    }

    public static async Task<IDocument> ParseUrlSynch(string Url)
    {
            var config = new Configuration().WithDefaultLoader();
            IDocument document = await BrowsingContext.New(config).OpenAsync(Url);

            return document;
    }

    public static async Task<ConcurrentBag<IDocument>> GetAllPagesDOMs(IDocument initialDocument)
    {

        ConcurrentBag< IDocument> AllPagesDOM = new ConcurrentBag< IDocument>();
        IDocument nextPageDOM;
        IDocument currentDocument = initialDocument;

        if (initialDocument != null)
        {
            AllPagesDOM.Add(initialDocument);
        }

        while (ContainsNextPage(currentDocument))
        {
            String nextPageUrl = GetNextPageUrl(currentDocument);

            nextPageDOM = ParseUrlSynch(nextPageUrl).Result;
            if (nextPageDOM != null)
                AllPagesDOM.Add(nextPageDOM);

            currentDocument = nextPageDOM;
        }

        return AllPagesDOM;
    }

      static void Main(string[] args)
    {



        List<IDocument> allPageDOMs = new List<IDocument>();
        IDocument initialDocument = ParseUrlSynch(InitialUrl).Result;
        List<String> urls = new List<string>();
        List<Subject> subjects = new List<Subject>();
        IHtmlCollection<IElement> subjectAnchors = initialDocument.QuerySelectorAll(".course_title a");

        String[] TitleAndCode;
        String Title;
        String Code;
        String Description;
        IDocument currentDocument = initialDocument;


        ConcurrentBag<IDocument> documents =          

        GetAllPagesDOMs(initialDocument).Result; //Exception in here
        ...
}
4

2 回答 2

0

错误消息是由此代码引起的:

document.QuerySelectorAll(".prevnext a")[0]

您的一份文件里面没有任何锚点prevnext。也许它是第一页,也许是最后一页,无论哪种方式,您都需要检查数组的长度。

此外,阻塞对异步方法的调用是一种不好的做法,应该避免。您将在任何 UI 应用程序中遇到死锁。您现在没有得到它的唯一原因是您在控制台应用程序中。

于 2017-04-17T00:47:25.030 回答
0

您的直觉是正确的,如果您从具有非默认设置的应用程序(SynchronizationContext例如 WPF、Win Forms 或 ASP.NET)中使用它,那么您将遇到死锁,因为您在async Task返回函数上同步阻塞(这很糟糕,应该避免)。当第一个await到达阻塞调用内部时,它会尝试将延续发布到 current SyncronizationContext,它已经被阻塞调用锁定(如果你使用.ConfigureAwait(false)你可以避免这种情况,但在这种情况下这是一个 hack)。

一个快速的解决方法是通过更改一直使用异步:

nextPageDOM = ParseUrlSynch(nextPageUrl).Result;

和:

nextPageDOM = await ParseUrlSynch(nextPageUrl);

在你被这个刺痛了几次之后,你就会学会在每次阻塞异步方法时让警钟在你的脑海中响起。

于 2017-04-15T18:15:29.300 回答