我正在处理用VB.Net编写的遗留应用程序。我的任务是使用Paralel任务库并线程化应用程序。大部分"工作"是一个以SqlDataReader对象为中心的while循环。为了开发人员的功劳,它被分解为逻辑方法和一个真正的工作方法。主要问题是处理各个任务的所有方法都接受SqlDataReader作为参数。我知道SqlDataReader并不是真正的线程安全,并且它的使用方式根本不是线程安全的。我想要做的是将SqlDataReader转换为ConcurrentQueue或IEnumerable,然后让#34; work"线程并处理该集合中的数据:
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
在这些方法中,rdr在ex:
的那些方法中起作用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
我不确定这是否合理或是解决这个问题的最佳方法,但这是我想到的第一件事。
任何建议?
答案 0 :(得分:2)
如果您将数据库读取器代码放入迭代器函数中,那么将为您提供将其转换为IEnumerable
的方法,例如
Iterator Function ReadMyObjects() As IEnumerable(Of MyObject)
Using cn = New SqlConnection("...")
cn.Open()
Using cmd = New SqlCommand("...", cn)
Using rdr = cmd.ExecuteReader()
If rdr.HasRows Then
While rdr.Read()
Yield New MyObject() With {
.PropA = rdr.GetString(rdr.GetOrdinal("A"))
}
End While
End If
End Using
End Using
End Using
End Function
然后您可以在并行循环中使用它:
Parallel.ForEach(
ReadMyObjects(),
Sub(item As MyObject)
' do something with item
End Sub
)