我有一个代码,可以在xmlnodelist中的节点上迭代,并根据节点名称为每个对象创建一个不同的对象,并将其添加到列表中以进行打印。
For Each node as XmlNode In nodeList
Select Case node.Name.ToUpper()
Case "SHAPE"
_items.Add(New ShapeTemplate(node, Me))
Case "TEXTBLOCK"
_items.Add(New TextblockTemplate(node, Me))
End Select
Next
此代码正常工作,但是由于Shapetemplate和TextBlockTemplate构造函数必须完成的所有工作,因此非常慢。由于将订单对象添加到_items并不重要,因此我认为加快其加快的好方法是使用平行循环。问题是XMLnodelist不能与并行使用。我一直在研究将XMLNODELIST转换为列表(XMLNODE的)而没有运气的方法。我一直看到的答案是
Dim nodes as New List(Of xmlNode)(nodeList.Cast(Of xmlNode)())
但是,当我尝试时,我会发现一个错误告诉我,"铸造"不是xmlnodelist的成员。
我也尝试使用像这样的trycast
Dim nodes as List(Of XmlNode) = TryCast(CObj(nodeList), List(Of XmlNode))
,但由于无法施放对象,因此导致节点没有。
有人知道我如何在并行中使用xmlnodelist。
编辑:如果我可以
您可以使用并行LINQ代替Parallel.ForEach
,这似乎更自然地适合这种转换。这看起来像是普通的LINQ查询,但是添加了.AsParallel()
。
Imports System.Linq
' _items will not be in same order as nodes in nodeList.
' Add .AsOrdered() after .AsParallel() to maintain order, if needed.
_items = (
From node In nodeList.Cast(Of XmlNode)().AsParallel()
Select item = CreateTemplate(node)
Where item IsNot Nothing
).ToList()
Function CreateTemplate(node As XmlNode) As ITemplate ' interface or base class for your types
Dim item As ITemplate
Select Case node.Name.ToUpper()
Case "SHAPE"
item = New ShapeTemplate(node, Me)
Case "TEXTBLOCK"
item = New TextblockTemplate(node, Me)
Case Else
item = Nothing
End Select
Return item
End Function
如下所示,可以通过将其传递给使用OfType
的构造函数将XmlNodeList
转换为通用List(Of XmlNode)
。
' I added so your code could compile.
' I assumed an interface shared by ShapeTemplate and TextblockTemplate
Dim nodeList As XmlNodeList
Dim _items As New List(Of ITemplate)
Dim _nodes As New List(Of XmlNode)(nodeList.OfType(Of XmlNode))
现在是平行循环。请注意,如果要添加到诸如List
之类的非TheadReadSafe集合中,则需要同步将对象添加到列表中。因此,我将耗时的部分(模板构造函数)与快速操作(添加到列表中)分开。这应该可以提高您的表现。
Dim oLock As New Object
Parallel.ForEach(
_nodes,
Sub(node)
Dim item As ITemplate
Select Case node.Name.ToUpper()
Case "SHAPE"
item = New ShapeTemplate(node, Me)
Case "TEXTBLOCK"
item = New TextblockTemplate(node, Me)
Case Else
item = Nothing ' or, do something else?
End Select
SyncLock oLock
_items.Add(item)
End SyncLock
End Sub)