Я имею дело с устаревшим заявлением, написанным на VB.Net. Мне было поручено использовать библиотеку задач Paralel и потоковое приложение. Основная часть «работы» находится в одном цикле, который центрируется вокруг объекта SqlDataReader. К чести разработчика он разбит на логические методы и один реальный метод работы. Основная проблема заключается в том, что все методы, которые обрабатывают отдельные задачи, принимают SqlDataReader в качестве параметра. Я знаю, что SqlDataReader на самом деле не является потокобезопасным и в том смысле, что он не использует поточный сейф вообще. То, что я хочу сделать, я думаю, конвертировать SqlDataReader в ConcurrentQueue или IEnumerable, а затем просто «работа» нить и работа над данными в этой коллекции:Как сделать SqlDataReader потоком безопасным/конвертировать в потокобезопасный тип
Using Command As New SqlCommand(StoredProcedure, Connection)
Command.CommandType = CommandType.StoredProcedure
Command.CommandTimeout = 0
Command.Parameters.Add("@Carrier", SqlDbType.VarChar, 50).Value = sCarrier
Using Reader As SqlDataReader = Command.ExecuteReader
If Reader.HasRows = True Then
SetReaderOrdinals(Reader)
Adjustments = New StringBuilder
'TODO this appears to be the bulk of the work in the application
While Reader.Read
Adjustments.Clear()
CommitCount += 1
If Reader.IsDBNull(SomeValue) = False Then
Select Case stuff
Case 1
DoThingForOne(Reader)
Case 2
DoThingForTwo(Reader)
Case 3
DoThingForThree(Reader)
Case 4
DoThingForFour(Reader)
Case 5
DoThingForFive(Reader)
Case 6
DoThingForSix(Reader)
Case Else
'Log something
Exit While
End Select
Else
'We Failed
End If
End While
Внутри этих методов РДР действует в те методы например:
If Rdr.GetString(SomeValue).Trim.Length >= 5 Then
If Rrd.IsDBNull(SomeValue)
Rrd.GetInt32(SomeValue)
то, что я хотел бы сделать что-то вроде:
'I know this isn't how you convert it but I am not sure how you do
Dim rows AS IEnumerable(of MyObject) = Reader
'Create threads and spawn them here
'act upon the collection here in many threads
Parallel.For Each row in rows
'Do row stuff here
If row Not Nothing Then
Select Case stuff
Case 1
DoThingForOne(row)
Case 2
DoThingForTwo(row)
Case 3
DoThingForThree(row)
Case 4
DoThingForFour(row)
Case 5
DoThingForFive(row)
Case 6
DoThingForSix(row)
Case Else
'Log something
Exit For
End Select
Else
'We Failed
End If
End For
Я не уверен, если это правдоподобно или лучший способ справиться с этим, но это первый й что пришло в голову.
Любые предложения?
Мне нравится этот подход; однако я не понимаю, что вы делаете в цикле. Я в основном C# dev, и я просто прикрываю его VB. Я знаю, что базовый код тот же. Что вы делаете с частью Sub (item) там? Это то же самое, что и в C#, указывающем элемент var в ReadMyObjects()? – Robert
Элементы 'Sub (item)' являются [лямбда-выражением] (https://msdn.microsoft.com/en-us/library/bb531253.aspx) - эквивалент C# будет похож на 'Parallel.ForEach (ReadMyObjects(), item => {// делаем что-то здесь}) '. Sub будет вызываться один раз для каждого элемента, возвращаемого 'ReadMyObjects', и это будет происходить параллельно по нескольким потокам. – Mark