我正在使用HtmlAgilityPack
和Parallel.Invoke
,特别是我有一个名为Table
的类,其中包含以下实现:
public class Table
{
HtmlDocument doc = new HtmlDocument();
public void Foo1()
{
doc.LoadHtml("some html");
}
public void Foo2()
{
doc.LoadHtml("some html");
}
public void Foo3()
{
doc.LoadHtml("some html");
}
}
现在的问题是,如果我这样做:
Table table = new Table();
Parallel.Invoke(
() => table.Foo1(),
() => table.Foo2(),
() => table.Foo3());
我会得到:
意外错误
来自 HtmlAgilityPack 的例外,特别是在第三种方法上。我可以看到,同时该对象被其他两种方法使用(当然,我使用的是 Parallel(。
如果我调用该方法而没有Parallel
一切正常,我该如何管理这个问题?
堆栈跟踪:
at HtmlAgilityPack.HtmlNodeCollection.Append(HtmlNode node( in C:\Users\Jonathan\Desktop\Z\zzzproject\HtmlAgilityPack\HtmlAgilityPack.Shared\HtmlNodeCollection.cs:line 321at HtmlAgilityPack.HtmlNode.AppendChild(HtmlNode
newChild( in C:\Users\Jonathan\Desktop\Z\zzzproject\HtmlAgilityPack\HtmlAgilityPack.Shared\HtmlNode.cs:line 818
at HtmlAgilityPack.HtmlDocument.PushNodeEnd(Int32 index, Boolean close( in C:\Users\Jonathan\Desktop\Z\zzzproject\HtmlAgilityPack\HtmlAgilityPack.Shared\HtmlDocument.cs:line 1882
at HtmlAgilityPack.HtmlDocument.Parse(( in C:\Users\Jonathan\Desktop\Z\zzzproject\HtmlAgilityPack\HtmlAgilityPack.Shared\HtmlDocument.cs:line 1424
at HtmlAgilityPack.HtmlDocument.Load(TextReader reader( in C:\Users\Jonathan\Desktop\Z\zzzproject\HtmlAgilityPack\HtmlAgilityPack.Shared\HtmlDocument.cs:line 706
at HtmlAgilityPack.HtmlDocument.LoadHtml(String html( in C:\Users\Jonathan\Desktop\Z\zzzproject\HtmlAgilityPack\HtmlAgilityPack.Shared\HtmlDocument.cs:line 752
at SWP.Controllers.TableController.GetAttendanceTable(Int32 seasonId, Int32 competitionId, Int32 roundId, Int32 groupId(
您正在尝试异步加载 html 到同一个 HtmlDocument 对象,几乎没有库准备好处理非静态类的异步修改,这就是(在某些部分(存在锁定的原因。我猜每次您将 HTML 加载到对象时,它都会重新启动 HTML 节点的树节点数据结构,从而搞砸一切。
如果你想解析/读取 HtmlDocument 对象异步,那么这将是一回事,但你正在主动写入 HtmlDocument 对象,这意味着乱序程序执行可能会将对象属性设置为 null,同时也尝试遍历该属性。