0

我在嵌套的 Parallel.For 循环 (vb.net) 中调用了一个子例程 MyPartsMatrix。MyPartsMatrix 需要一个名为“未填充”的变量,该变量通过 ByRef 传递,因为该值在 MyPartsMatrix 子例程中被修改。在子例程 MyPartsMatrix 执行后,我需要获取并存储此值。

与使用普通嵌套 For...Next 循环的非并行代码相比,当我运行此代码的并行版本时,“未填充”变量会产生不同的值。我不明白为什么会这样。

从 Parallel.For 循环内部调用另一个子例程是否线程安全?

这个变量“未填充”线程安全吗?

    Dim ConcurrentListofResults As ConcurrentQueue(Of FindBestResults)
    ConcurrentListofResults = New ConcurrentQueue(Of FindBestResults)

    Dim x = 5, y = 5

    Parallel.For(0, x, Sub(oD)
                           Parallel.For(0, y, Sub(oT)

                                                  Dim unfilled As Integer = 0
                                                  MyPartsMatrix (oD, oT, unfilled)

                                                  'Create a FBS item to add to the concurrent list collection
                                                  Dim FBSResultsItem = New FindBestResults
                                                  FBSResultsItem.oD = oD
                                                  FBSResultsItem.oT = oT
                                                  FBSResultsItem.unfilled = unfilled

                                                  'Add this item to the Concurent collection
                                                  ConcurrentListofResults.Enqueue(FBSResultsItem)

                                              End Sub)
                       End Sub)
    'Get best result.
    Dim bestResult As FindBestResults
    For Each item As FindBestResults In ConcurrentListofResults
        If item.unfilled < bestResult.unfilled Then
            bestResult.oD = item.oD
            bestResult.oT = item.oT
            bestResult.unfilled = item.unfilled
        End If
    Next

    Public Sub MyPartsMatrix (ByVal oD As Integer, ByVal oT As Integer, ByRef unfilled As Integer)

      '....do stuff with the unfilled variable....
      'unfilled is a counter that is incremented while we run through the PartsMatrix
       unfilled = unfilled + 1  
    End Sub

如果这不是线程安全的,是否有另一种方法来编写它,以便“未填充”变量是线程安全的,或者使调用另一个子例程线程安全?

4

1 回答 1

0

如果没有MakeSchedule(您MyMakePartsMatrix在另一个地方调用过)的定义,就不可能说它是否是线程安全的。

为了线程安全,sub 不需要修改除未填充之外的任何内容。这将确保使用相同的输入多次调用它总是会产生相同的输出。我还建议转换为函数,因为我发现这更容易理解发生了什么。

另一个注意事项:

如果您不嵌套并行循环,您的性能会更好。您目前正在等待您的内部循环完成,然后再启动您的第二个循环。如果您使用更大的 x + y 值,那么类似于代码的内容会更好。

    Dim scenarios = From x2 In Enumerable.Range(0, x)
        From y2 In Enumerable.Range(0, y)
        Select New With {x2, y2}

    Parallel.ForEach(scenarios, Sub(s)

                                End Sub)
于 2016-09-15T09:02:44.227 回答