Member 11856456 Ответов: 1

Почему parallel for добавляет дубликаты строк, когда я меняю второе число, и как я могу остановить это?


Благодаря Ричарду я смог сделать еще один шаг вперед и включил его дополнительное кодирование в свой текущий проект.

Public Sub Match_Merge(I As Long)


Это метод, для которого я вызываю параллель.

внутри этого метода я сравниваю свою временную таблицу, которая является моей таблицей импорта, и текущую таблицу базы данных.

For I = 1 To temptable.Rows.Count - 1

                    countI = countI + 1
                    'this will be table 2

                    For I2 = I3 To dt.Rows.Count - 1
Next I
Next i2


если нет совпадения то это информация идет к
removeduptable.ImportRow(temptable.Rows(I))


если есть совпадение, то информация хранится в отдельной таблице.
duplicaterow = Duplicatetable.NewRow()
                            duplicaterow.Item("First_name") = dt.Rows(I2).Item("First_name")
                            duplicaterow.Item("Middle_name") = dt.Rows(I2).Item("Middle_name")
                            duplicaterow.Item("Last_name") = dt.Rows(I2).Item("Last_name")
                            duplicaterow.Item("Duplicatecount") = count

                            'add rows to table
                            Duplicatetable.Rows.Add(duplicaterow)


Это метод, который я использую для своей параллели для:
Public Sub ParallelForEach(ByVal startOfIteration As Integer, ByVal endOfIteration As Integer, ByVal subFunctionName As String)

        processorcount.MaxDegreeOfParallelism = 4
        Const flags As BindingFlags = BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Static Or BindingFlags.Instance

        ' Find the method with the specified name which accepts a single Integer parameter:
        Dim method As MethodInfo = Me.GetType().GetMethod(subFunctionName, flags, Nothing, New Type() {GetType(Long)}, Nothing)

        If method Is Nothing Then
            Throw New ArgumentException(String.Format("Method '{0}' was not found.", subFunctionName), "subFunctionName")
        End If

        ' Create a delegate of the correct type pointing to the method:
        Dim del As System.Delegate
        If method.IsStatic Then
            del = System.Delegate.CreateDelegate(GetType(Action(Of Long)), method)
        Else
            del = System.Delegate.CreateDelegate(GetType(Action(Of Long)), Me, method)
        End If

        ' Cast the delegate to the correct type:
        Dim action As Action(Of Long) = DirectCast(del, Action(Of Long))

        ' NB: Second parameter to Range is the number of items to return, not the last number to return:
        '      Dim numbers As IEnumerable(Of Long) = Enumerable.Range(startOfIteration, 1 + endOfIteration - startOfIteration)


        System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = False
        System.Threading.Tasks.Parallel.For(1, 2, processorcount, action)
        
    End Sub


Если я оставлю параллель вот так:
System.Threading.Tasks.Parallel.For(1, 2, processorcount, action)
он работает так же быстро, как и последовательный.

если я изменю его на
System.Threading.Tasks.Parallel.For(1, 10, processorcount, action)
он работает быстрее, но параллель для добавления в повторяющиеся строки.

Так что если количество записей равно 150 000, то оно будет отображаться как 300 000, и я не могу найти способ остановить это.

Что я уже пробовал:

Я попытался отрезать добавление строк, когда подсчет достиг количества заманчивых строк. Я также попытался синхронизировать обе таблицы, и это тоже не помогло.

1 Ответов

Рейтинг:
1

Dave Kreskowiak

Прежде всего, класс DataTable является потокобезопасным только для чтения. Для записи в объект DataTable из нескольких потоков они должны быть синхронизированы. Это означает, что только один поток должен быть разрешен для записи в таблицу в любой момент времени.


Member 11856456

Я читал о синхронизации, однако не могу найти никаких хороших примеров, чтобы показать, как это сделать с таблицами данных. Из того, что я собираю, чтение и сравнение - это прекрасно. Каков наилучший подход в подобных ситуациях?

Dave Kreskowiak

Синхронизация в этом случае очень проста. Все, что вам нужно, это объект блокировки.

Dim lock As Object
.
.
.
SyncLock lock
    ' Code to create a new row in the DataTable
    ' and write the new row data.
End SyncLock

Member 11856456

Дэйв, я пробовал это сделать, но там написано "значение не может быть нулевым", под объектом блокировки есть зеленая линия, что должно быть привязано к этому объекту?

Dave Kreskowiak

Возгласы. Так и должно быть

Dim lock As New Object

Member 11856456

Эй, Дэйв, я пытался использовать это так, как вы предложили, и я пытался поместить это в другие части моего кода, и я все еще не мог заставить это работать. Мне кажется, я что-то упускаю. Но я хотел попробовать пару вещей, прежде чем отправлю сообщение обратно.