Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 数组的问题时间不够长_Vb.net - Fatal编程技术网

Vb.net 数组的问题时间不够长

Vb.net 数组的问题时间不够长,vb.net,Vb.net,我每分钟调用此函数数千次,以获得平均延迟,但在运行约20或30分钟后,我的应用程序崩溃。。知道为什么会这样吗 源数组不够长。检查srcdex和length,以及数组的下限 Dim iLatency_Average As New List(Of Long) Public Function Average_Latency(myLatency As Long) As Long iLatency_Average.Insert(0, myLatency) If iLatency_Ave

我每分钟调用此函数数千次,以获得平均延迟,但在运行约20或30分钟后,我的应用程序崩溃。。知道为什么会这样吗

源数组不够长。检查srcdex和length,以及数组的下限

Dim iLatency_Average As New List(Of Long)
Public Function Average_Latency(myLatency As Long) As Long

    iLatency_Average.Insert(0, myLatency)

    If iLatency_Average.Count = 25 Then
        Dim allLatency() As Long = iLatency_Average.ToArray()

        Array.Sort(allLatency)

        Dim iAverage As Long
        For i As Integer = 5 To 19
            iAverage += allLatency(i)
        Next

        iLatency_Average.RemoveAt(24)

        Return CLng(iAverage / 15)
    Else
        Return 0
    End If
End Function

你可以使用同步锁。而且,您似乎在使用a的属性,而不是列表。请注意,每次使用集合时都必须调用SyncLock

Dim iLatency_Average As New Queue(Of Long)

Public Function Average_Latency(ByVal myLatency As Long) As Long

    Dim allLatency() As Long = Nothing

    ' Add the new latency
    SyncLock iLatency_Average
        iLatency_Average.Enqueue(myLatency)

        If iLatency_Average.Count = 25 Then
            allLatency = iLatency_Average.ToArray()
            iLatency_Average.Dequeue()
        End If
    End SyncLock

    ' Calculate average
    If allLatency IsNot Nothing Then
        Array.Sort(allLatency)

        Dim iAverage As Long
        For i As Integer = 5 To 19
            iAverage += allLatency(i)
        Next

        Return CLng(iAverage / 15)
    Else
        Return 0
    End If
End Function

我也把你的逻辑分成两部分。一部分用于添加新值,另一部分用于计算平均值。

此版本不使用SyncLock(速度较慢),但它使用的是BlockingCollection评论上发布的建议

Dim iLatency_Average As New Concurrent.BlockingCollection(Of Long)(25)
Public Function Average_Latency(myLatency As Long) As Long

    iLatency_Average.TryAdd(myLatency)

    If iLatency_Average.Count = 25 Then
        Dim allLatency() As Long = iLatency_Average.ToArray

        Array.Sort(allLatency)

        Dim iAverage As Long
        For i As Integer = 5 To 19
            iAverage += allLatency(i)
        Next

        iLatency_Average.TryTake(0)

        Return CLng(iAverage / 15)
    Else
        Return 0
    End If
End Function

因为看起来您想要保证最后25次观察的滑动窗口,所以不使用锁可能会有问题。不过,这是一把相对便宜的锁

正如@the_lotus提到的,将队列操作从实际平均值中分离出来要快得多

请参阅下面的代码,其中有10个任务,每个任务增加100000个延迟。我平均每1000000次操作大约400毫秒。包括一个ArraySegment(Long)和一个LINQ选项用于比较

Private RecentLatencies As New Queue(Of Long)

Public Sub Main()
    With New Stopwatch
        .Start()

        Task.WhenAll(Enumerable.Range(1, 10).Select(Function(x) Task.Run(Sub()
                                                                            For m = 1 To 100000
                                                                                LogLatencyAndGetSlidingAverage(m)
                                                                            Next
                                                                         End Sub))).Wait()

        .Stop()

        Console.WriteLine("All done...{0}ms", .ElapsedMilliseconds)
        Console.ReadKey()
    End With
End Sub

Private Function LogLatencyAndGetSlidingAverage(latency As Long) As Long
    Dim l As Long() = Nothing

    SyncLock RecentLatencies
        RecentLatencies.Enqueue(latency)

        If RecentLatencies.Count = 25 Then
            l = RecentLatencies.ToArray()
            RecentLatencies.Dequeue()
        End If
    End SyncLock

    'option 1
    If l IsNot Nothing Then
        Array.Sort(l)

        Dim sum As Long

        For i = 5 To 19
            sum += l(i)
        Next

        Return sum \ 15
    Else
        Return 0
    End If

    'option 2 - ArraySegment
    'If l IsNot Nothing Then
    '    Array.Sort(l)
    '    Return CLng(New ArraySegment(Of Long)(l, 5, 15).Average)
    'Else
    '    Return 0
    'End If

    'option 3 - LINQ
    'Return CLng(If(l IsNot Nothing, l.OrderBy(Function(n) n).Skip(5).Take(15).Average, 0))
End Function

听起来你可能在多个线程中调用它<代码>列表不是线程安全的。是的,这是正确的,您建议线程安全函数使用什么?您可以使用同步,也可以使用线程安全集合。老实说,你可能会让这段代码更高效——每次调用时调用
Insert(0,…)
都是一个糟糕的开始……我想你可以使用列表锁定(see)对象,但这会让你的应用程序慢很多。正如@JonSkeet所提到的,有很多更好的方法来解决这个问题并组织代码。看看这个名称空间中的其他集合。我会检查数组的大小。可能性很小,但有可能在检查计数和调用ToArray之间清除集合。还取决于代码的其余部分。