我有一个包含许多属性Integer
和Single
的类。我想以多线程方式使用该类,以便属性可以用作累加器(该类是报告方案的基础)。所以我希望能够做到这样的事情:
Public Class ReportTotals
Property Count As Integer
Property Total As Single
Property Tax As Single
Property Shipping As Single
Property ItemsSold As Integer
Public Function GetReport() As String
...
End Function
End Class
Public Function BuildReportData As ReportTotals
Dim myReport As New ReportTotals
With myReport
Parallel.ForEach(UserSales, Sub(userSale)
.Count += 1
.Total += userSale.Total
.Tax += userSale.Tax
.Shipping += userSale.Shipping
.ItemsSold += userSale.ItemsSold
'more complicated stuff and property assignments
End Sub)
End With
End Function
根据我的研究,我知道Integer
和Single
是原子的,但我不确定这是否扩展到属于类的整数。我不想假设,因为多线程的错误可能会在以后出现并咬我。
更新:显然,Single
不是线程安全的,所以我必须对那个使用锁定,但Integer
呢?
答案 0 :(得分:3)
您可以使用Interlocked.Increment以原子方式递增整数,即使它们是类成员。
答案 1 :(得分:1)
这听起来像你想要的an overload of Parallel.ForEach()
that works with local state。
在localInit
委托中,您将创建ReportTotals
的新实例,并在localFinally
中将本地ReportTotals
的值添加到全局{{1}}下一把锁。
答案 2 :(得分:0)
也许SyncLock正是您所寻找的。 p>
Public Sub sale(s As String)
SyncLock _lock
//'thread safe code'
End SyncLock
End Sub
Public Function BuildReportData as ReportTotals
Dim myReport As New ReportTotals
With myReport
Parallel.ForEach(UserSales, sale(userSale))
End Function
答案 3 :(得分:0)
我决定做的事情,至少在有人有更好的想法之前,就是在ReportTotals
例程中创建大量Parallel.ForEach
个对象并将它们全部放入ConcurrentBag
。然后,在Parallel.ForEach
语句结束后,我使用常规For Each
语句将ReportTotals
中ConcurrentBag
个对象中的所有值累积到新的ReportTotals
对象中然后我回来了。
所以我正在做这样的事情:
Public Class ReportTotals
Property Count As Integer
Property Total As Single
Property Tax As Single
Property Shipping As Single
Property ItemsSold As Integer
Public Function GetReport() As String
...
End Function
End Class
Public Function BuildReportData As ReportTotals
Dim myReport As New ReportTotals
Dim myReports As New ConcurrentBag(Of ReportTotals)
Paralle.ForEach(UserSales, Sub(userSale)
Dim workingReport As New ReportTotals
With workingReport
.Count += 1
.Total += userSale.Total
.Tax += userSale.Tax
.Shipping += userSale.Shipping
.ItemsSold += userSale.ItemsSold
'more complicated stuff and property assignments
End With
End Sub)
For Each report In myReports
With myReport
.Count += report.Count
.Total += report.Total
.Tax += report.Tax
.Shipping += report.Shipping
.ItemsSold += report.ItemsSold
End With
Next
Return myReport
End Function