我有一段代码迭代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并不重要,我认为加快它的一个好方法是使用parallel.ForEach循环。问题是XmlNodeList不能与parallel.ForEach一起使用,因为它是非泛型集合。我一直在研究如何将XmlNodeList转换为List(Of XmlNode)而没有运气。我一直看到的答案是
Dim nodes as New List(Of xmlNode)(nodeList.Cast(Of xmlNode)())
但是当我尝试它时,我收到一个错误,告诉我' Cast'不是XmlNodeList的成员。
我也试过像这样使用TryCast
Dim nodes as List(Of XmlNode) = TryCast(CObj(nodeList), List(Of XmlNode))
但是它会导致节点无效,因为无法投射对象。
有没有人知道如何在parallel.ForEach循环中使用XmlNodeList?
编辑:如果我可以
,我试图避免使用循环进行转换答案 0 :(得分:1)
如here所示,XmlNodeList
可以通过List(Of XmlNode)
传递给构造函数来转换为通用OfType
。
' 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
),则需要同步将对象添加到列表中。所以我将耗时部分(模板构造函数)与快速操作(添加到列表)分开。这可以改善您的表现。
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)
答案 1 :(得分:1)
您可以使用Parallel 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