Q:

VB.NET For Loop too slow when grabbing XML

I am getting values from an XML file (a resources file), and basically inserting them into a datatable. I have 679 keys to get from the resource file, and this takes 3.41 seconds. I was wondering if there is any way of making this loop faster. 
I have tried the Parallel.For loop, but I found that it is unstable because it begins inserting a row when the previous insert didn't finish. I used synch block, but then the speed went back to 3.41.
 For idx As Integer = 0 To KeyNames.Length - 1
        With KeyManagerResource.Instance
            DataTableManager.Instance.InsertRow(KeyNames(idx), .GetKeyValue(KeyNames(idx), DynamicProperties.Instance.EnglishResourcePath), _
                                                               .GetKeyValue(KeyNames(idx), DynamicProperties.Instance.FrenchResourcePath))
        End With
    Next
 ''' <summary>
''' Gets the value of the key.
''' </summary>
''' <param name="ID">ID of the key.</param>
''' <returns>Value of the key.</returns>
''' <remarks></remarks>
Overrides Function GetKeyValue(ID As String, File As String) As String

   'Sets the current path of the XMLReader to the english file.
    XMLManager.Instance.SetReaderPath(File)

    Dim returnedNode As Xml.XmlNode = XMLManager.Instance.GetNode(String.Format("//data" & Helper.CaseInsensitiveSearch("name"), "'" & ID.ToLower & "'"))

    If returnedNode IsNot Nothing Then
        Return returnedNode.ChildNodes(1).InnerText
    Else
        Return ""
    End If

End Function

 ''' <summary>
''' Adds a row to the target table.
''' </summary>
''' <param name="RowValues">The row values we want to insert. These are in order, so it is presumed the first row value in the array is for the first column 
''' of the target data table.</param>
''' <remarks></remarks>
Public Sub InsertRow(ByVal ParamArray RowValues() As String)

    'If the length of the RowValues is not equal the columns, that means that is an invalid insert. Throw exception.
    If RowValues.Length = dtTargetTable.Columns.Count Then

        'Creates a new row.
        Dim drNewRow As DataRow
        drNewRow = dtTargetTable.NewRow

        'Goes through the row values.
        For idx As Integer = 0 To RowValues.Length - 1

            'Store the value for the column.
            drNewRow(dtTargetTable.Columns(idx)) = RowValues(idx)

        Next

        'Only adds the key if the primary key doesn't already exist.
        If dtTargetTable.Rows.Find(RowValues(0)) Is Nothing Then
            'Adds the row to the table.
            dtTargetTable.Rows.InsertAt(drNewRow, 0)
        End If

    Else
        Throw New Exception(String.Format("Invalid insert. The number of row values passed are not equal to the number of columns of the target dataTable." & _
                                          "The number of columns of the target dataTable are {0}.", dtTargetTable.Columns.Count))
    End If

End Sub

A:

I have several suggestions that should help:
Don't retrieve the keyname using index multiple times; using a For Each loop reduces that amount of processing.
Don't swap XML files in each loop; instead, initialize instances outside of the loop and pass them to the appropriate method (not sure what the instance type is, so I made one up called XMLManagerInstance).
Don't check for primary key existence in the datatable on each loop. Instead, keep a list of the previously used primary keys in the outer loop and don't bother doing any work if the PK already exists.
These should help improve your performance quite a bit, especially the last two.
Here is a suggested reworking of the code:
    Dim KeyNames As List(Of String)

    Dim cPrimaryKeys As New System.Collections.Generic.HashSet(Of String)
    Dim oEnglishFile As XMLManagerInstance
    Dim oFrenchFile As XMLManagerInstance

    oEnglishFile.SetReaderPath(DynamicProperties.Instance.EnglishResourcePath)
    oFrenchFile.SetReaderPath(DynamicProperties.Instance.FrenchResourcePath)

    For Each KeyName As String In KeyNames
        If Not cPrimaryKeys.Contains(KeyName) Then
            cPrimaryKeys.Add(KeyName)
            With KeyManagerResource.Instance
                DataTableManager.Instance.InsertRow(KeyName, .GetKeyValue(KeyName, oEnglishFile), .GetKeyValue(KeyName, oFrenchFile))
            End With
        End If
    Next

''' <summary>
''' Gets the value of the key.
''' </summary>
''' <param name="ID">ID of the key.</param>
''' <returns>Value of the key.</returns>
''' <remarks></remarks>
Public Function GetKeyValue(ID As String, FileInstance As XMLManagerInstance) As String

    Dim returnedNode As Xml.XmlNode = FileInstance.GetNode(String.Format("//data" & Helper.CaseInsensitiveSearch("name"), "'" & ID.ToLower & "'"))

    If returnedNode IsNot Nothing Then
        Return returnedNode.ChildNodes(1).InnerText
    Else
        Return ""
    End If

End Function

''' <summary>
''' Adds a row to the target table.
''' </summary>
''' <param name="RowValues">The row values we want to insert. These are in order, so it is presumed the first row value in the array is for the first column 
''' of the target data table.</param>
''' <remarks></remarks>
Public Sub InsertRow(ByVal ParamArray RowValues() As String)

    'If the length of the RowValues is not equal the columns, that means that is an invalid insert. Throw exception.
    If RowValues.Length = dtTargetTable.Columns.Count Then
        'Creates a new row.
        Dim drNewRow As DataRow

        drNewRow = dtTargetTable.NewRow

        'Goes through the row values.
        For idx As Integer = 0 To RowValues.Length - 1
            'Store the value for the column.
            drNewRow(dtTargetTable.Columns(idx)) = RowValues(idx)
        Next
    Else
        Throw New Exception(String.Format("Invalid insert. The number of row values passed are not equal to the number of columns of the target dataTable." & _
                                          "The number of columns of the target dataTable are {0}.", dtTargetTable.Columns.Count))
    End If

End Sub

