线程安全属性

时间:2013-04-22 20:49:40

标签: .net vb.net concurrency parallel-processing parallel.foreach

我有一个包含许多属性IntegerSingle的类。我想以多线程方式使用该类,以便属性可以用作累加器(该类是报告方案的基础)。所以我希望能够做到这样的事情:

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

根据我的研究,我知道IntegerSingle是原子的,但我不确定这是否扩展到属于类的整数。我不想假设,因为多线程的错误可能会在以后出现并咬我。

更新:显然,Single不是线程安全的,所以我必须对那个使用锁定,但Integer呢?

4 个答案:

答案 0 :(得分:3)

您可以使用Interlocked.Increment以原子方式递增整数,即使它们是类成员。

答案 1 :(得分:1)

这听起来像你想要的an overload of Parallel.ForEach() that works with local state

localInit委托中,您将创建ReportTotals的新实例,并在localFinally中将本地ReportTotals的值添加到全局{{1}}下一把锁。

答案 2 :(得分:0)

也许SyncLock正是您所寻找的。

 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语句将ReportTotalsConcurrentBag个对象中的所有值累积到新的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