我正在尝试使用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
...
}
答案 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应用程序中获得死锁。你现在没有得到它的唯一原因是你在控制台应用程序。