Vb.net 数组的问题时间不够长
我每分钟调用此函数数千次,以获得平均延迟,但在运行约20或30分钟后,我的应用程序崩溃。。知道为什么会这样吗 源数组不够长。检查srcdex和length,以及数组的下限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
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之间清除集合。还取决于代码的其余部分。