vb.net在平行的foreach中使用xmlnodelist



我有一个代码,可以在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)

最新更新