总结任务中返回的小数
Summing up decimals returned within task
我正在尝试 运行 通过 1-X 项的列表并在任务中处理它们以加快处理的完成速度(它们发出的网络请求有时可能需要很短的时间才能完成).我正在尝试对处理完成时返回的小数求和,而不是再次循环遍历列表。就像现在一样,总和被每个任务覆盖而不是添加到。
我可以在将小数加到总和之前插入一个短暂的停顿,这似乎工作正常,但我确信那里有更好的解决方案。
我看到有人提到过 SyncLock,但我不能在 Decimal 上使用它。
这是我写的一些测试代码。 .Process 方法只是等待一个随机的秒数并将 .Value 属性 设置为一个随机小数。
有什么改进和正确计算总和的建议吗?
Try
Dim lstItem As List(Of clsItem) = GetList()
Dim lstViewItem As New List(Of ListViewItem)
Dim lstTasks As New List(Of Task)()
Dim decTotal As Decimal = 0.0
For i As Int32 = 0 To lstItem.Count - 1
Dim j As Int32 = i
Dim t As Task = Task.Run(Sub()
lstViewItem.Add(New ListViewItem(New String() {j, lstItem(j).Process()}))
'System.Threading.Thread.Sleep(j * 1000)
decTotal += lstItem(j).Value
End Sub)
lstTasks.Add(t)
Next
Task.WaitAll(lstTasks.ToArray())
lstView.Items.AddRange(lstViewItem.ToArray())
lstView.Items.Add("")
lstView.Items.Add(decTotal)
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
您应该可以使用 SyncLock
来解决您的问题。 SyncLock 只能用于引用类型。所需要的只是创建一个在当前实例范围内的新对象,然后让 SyncLock
锁定该对象。
这是一个利用 SyncLock
的小型控制台应用程序。我大大简化了你所拥有的。我真的不想制作 listViews 之类的,而不是返回一个随机小数,它只是 returns 1 这样结果应该是循环迭代的次数。
Option Strict On
Option Explicit On
Imports System.Threading.Tasks
Module Module1
Sub Main()
Dim lstTasks As New List(Of Task)()
Dim SyncLockedTotal As Decimal = 0D
Dim decTotal As Decimal = 0D
Dim sLock As New Object
For i As Int32 = 1I To 1000I
Dim t As Task = Task.Run(Sub()
Dim tempDecimal As Decimal = clsItem.Process()
decTotal += tempDecimal
SyncLock sLock
SyncLockedTotal += tempDecimal
End SyncLock
End Sub)
lstTasks.Add(t)
Next
Task.WaitAll(lstTasks.ToArray())
Console.WriteLine(String.Format("Value for decTotal: {0}", decTotal.ToString))
Console.WriteLine(String.Format("Value for SyncLockedTotal: {0}", SyncLockedTotal.ToString))
Console.ReadLine()
End Sub
End Module
Public Structure clsItem
Public Shared Function Process() As Decimal
Dim rnd As New Random(DateTime.Now.Millisecond)
Threading.Thread.Sleep(rnd.Next(10I))
Return 1D
End Function
End Structure
注意:您的应用程序设置必须以 .NET 4.5 为目标才能使用 Task.Run()
,如果您以 .NET 4 为目标,则必须使用 Task.Factory.StartNew()
。如果您的目标是 .NET 3.5 或更低版本,这对您不起作用,因为您没有可用的 System.Threading.Tasks
命名空间。
我正在尝试 运行 通过 1-X 项的列表并在任务中处理它们以加快处理的完成速度(它们发出的网络请求有时可能需要很短的时间才能完成).我正在尝试对处理完成时返回的小数求和,而不是再次循环遍历列表。就像现在一样,总和被每个任务覆盖而不是添加到。
我可以在将小数加到总和之前插入一个短暂的停顿,这似乎工作正常,但我确信那里有更好的解决方案。
我看到有人提到过 SyncLock,但我不能在 Decimal 上使用它。
这是我写的一些测试代码。 .Process 方法只是等待一个随机的秒数并将 .Value 属性 设置为一个随机小数。
有什么改进和正确计算总和的建议吗?
Try
Dim lstItem As List(Of clsItem) = GetList()
Dim lstViewItem As New List(Of ListViewItem)
Dim lstTasks As New List(Of Task)()
Dim decTotal As Decimal = 0.0
For i As Int32 = 0 To lstItem.Count - 1
Dim j As Int32 = i
Dim t As Task = Task.Run(Sub()
lstViewItem.Add(New ListViewItem(New String() {j, lstItem(j).Process()}))
'System.Threading.Thread.Sleep(j * 1000)
decTotal += lstItem(j).Value
End Sub)
lstTasks.Add(t)
Next
Task.WaitAll(lstTasks.ToArray())
lstView.Items.AddRange(lstViewItem.ToArray())
lstView.Items.Add("")
lstView.Items.Add(decTotal)
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
您应该可以使用 SyncLock
来解决您的问题。 SyncLock 只能用于引用类型。所需要的只是创建一个在当前实例范围内的新对象,然后让 SyncLock
锁定该对象。
这是一个利用 SyncLock
的小型控制台应用程序。我大大简化了你所拥有的。我真的不想制作 listViews 之类的,而不是返回一个随机小数,它只是 returns 1 这样结果应该是循环迭代的次数。
Option Strict On
Option Explicit On
Imports System.Threading.Tasks
Module Module1
Sub Main()
Dim lstTasks As New List(Of Task)()
Dim SyncLockedTotal As Decimal = 0D
Dim decTotal As Decimal = 0D
Dim sLock As New Object
For i As Int32 = 1I To 1000I
Dim t As Task = Task.Run(Sub()
Dim tempDecimal As Decimal = clsItem.Process()
decTotal += tempDecimal
SyncLock sLock
SyncLockedTotal += tempDecimal
End SyncLock
End Sub)
lstTasks.Add(t)
Next
Task.WaitAll(lstTasks.ToArray())
Console.WriteLine(String.Format("Value for decTotal: {0}", decTotal.ToString))
Console.WriteLine(String.Format("Value for SyncLockedTotal: {0}", SyncLockedTotal.ToString))
Console.ReadLine()
End Sub
End Module
Public Structure clsItem
Public Shared Function Process() As Decimal
Dim rnd As New Random(DateTime.Now.Millisecond)
Threading.Thread.Sleep(rnd.Next(10I))
Return 1D
End Function
End Structure
注意:您的应用程序设置必须以 .NET 4.5 为目标才能使用 Task.Run()
,如果您以 .NET 4 为目标,则必须使用 Task.Factory.StartNew()
。如果您的目标是 .NET 3.5 或更低版本,这对您不起作用,因为您没有可用的 System.Threading.Tasks
命名空间。