使用轮询线程的BlockingCollection抓取重复项

时间:2018-05-29 19:18:44

标签: .net vb.net multithreading

我有一个阻塞集合,其中填充了数据库中的记录列表。

Public Shared BatchRecords As IThreadPool(Of BatchRecord) = New IThreadPool(Of BatchRecord)(Function()                                                                                                    Return New BatchRecord                                                                                                End Function, 20)

Public Shared Function GetOne(ThreadName As String) As BatchRecord
     Dim record As BatchRecord = BatchRecords.GetRecord()
     log.WriteLog("Thread:" & ThreadName & " Pool: " & Pool.ToString)
     Return record
End Function

Public Shared Sub AddOne(record As BatchRecord)
    BatchRecords.PutRecord(record)
End Sub

Task.Factory.StartNew(Sub()
                          PoolForBatchRecords()
                      End Sub)

For i As Integer = 0 To 20
    Task.Factory.StartNew(Sub()
                              Dim BatchGenerator As New GeneratorThread
                              Thread.CurrentThread.Name = (i + 1).ToString
                              BatchGenerator.Run()
                          End Sub)
Next

Inside GeneratorThread

Public Function Run()
    while true
        Dim record as MyRecord =  MyCollection.Take()
        'Do Work
    End While
End Function

我的20个任务正在查询BlockingCollection中的项目。但线程不断获得相同的项目。集合中没有重复项。事实上,当它开始66879524时,集合中只有一个项目。

Adding BatchId: 66879524 2018/05/29 14:20:01
Thread:1 picking up Batch ID:66879524  2018/05/29 14:20:02
Thread:2 picking up Batch ID:66879524  2018/05/29 14:20:02
Adding BatchId: 66879531 2018/05/29 14:20:02

1 个答案:

答案 0 :(得分:0)

最终在将项目添加到列表中时出现

20使所有线程都从数据库中检查项目进行处理。检查是在while循环中

Dim record As BatchRecord = Nothing
Dim keepChecking As Boolean = true
while keepChecking
    'Stop when we find a record
    keepChecking = CheckforWork(byRef record)
End While

BatchRecords.AddOne(record)

while循环应该在返回错误的keepChecking时立即停止,但是实际上设置了keepChecking时,while循环继续循环了2-3次。

我通过传入keepChecking byRef进行了修复,它将立即将变量设置为false,然后返回我发现的记录:

Dim record As BatchRecord = Nothing
Dim keepChecking As Boolean = true
while keepChecking
    'Stop when we find a record
    record = CheckforWork(byRef keepChecking)
End While

这不是确切的代码,当然还有一些其他检查,并且在检查之间会有一个暂停,以免影响数据库,尤其是当找到0条记录时。