进行异步调用时出现AngleSharp错误

时间:2017-04-14 18:53:57

标签: c# .net multithreading asynchronous anglesharp

我正在尝试使用AngleSharp加载许多页面。这个想法是它加载一个页面,如果这个页面有一个指向下一页的链接,加载下一页等等,这些方法就像下面描述的那样。但我得到了内在的例外:

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

我认为是与Thread和syncrhronization相关的事情。

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

2 个答案:

答案 0 :(得分:0)

您的直觉是正确的,如果您使用非默认#feedback { font-size: 1.4em; } #selectable .ui-selecting { background: #FECA40; } #selectable .ui-selected { background: #F39814; color: white; } #selectable { list-style-type: none; margin: 0; padding: 0; width: 60%; } #selectable li { margin: 3px; padding: 0.4em; font-size: 1.4em; height: 18px; }的应用程序(如WPF,Win Forms或ASP.NET)使用此直觉,那么您将遇到死锁,因为您正在同时阻止<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> <script src="https://code.jquery.com/jquery-1.12.4.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <ol id="selectable"> <li class="ui-widget-content">Item 1</li> <li class="ui-widget-content">Item 2</li> <li class="ui-widget-content">Item 3</li> <li class="ui-widget-content">Item 4</li> <li class="ui-widget-content">Item 5</li> <li class="ui-widget-content">Item 6</li> <li class="ui-widget-content">Item 7</li> </ol> SynchronizationContext返回功能(这很糟糕,应该避免)。当第一个async到达阻止调用内部时,它会尝试将延续发布到当前Task,这将被阻止调用锁定(如果您使用await你避免这样做,但在这种情况下这是一个黑客攻击。)

快速解决方法是通过更改:

一直使用异步
SyncronizationContext

使用:

.ConfigureAwait(false)

在你被这几次叮叮当当之后,每当你阻止异步方法时,你都会学会在脑子里敲响警钟。

答案 1 :(得分:0)

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

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

您的一个文档在prevnext内没有任何锚点。也许这是第一页,也许是最后一页,你需要检查数组的长度。

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