如下程序同步运行后返回不正确 ,应该返回300万,实际返回了400万。
Imports
System.Collections.Concurrent
Public
Class
Class1
Private
ConCurrentBag1
As
New
ConcurrentBag(Of
Integer
)
'在这里创建ConcurrentBag,运行结果发生错误。
Sub
MySub()
Dim
Task1
As
New
Task(Of ConcurrentBag(Of
Integer
))(
AddressOf
MyFunc)
Dim
Task2
As
New
Task(Of ConcurrentBag(Of
Integer
))(
AddressOf
MyFunc)
Task1.RunSynchronously()
Task2.RunSynchronously()
Dim
List1
As
New
List(Of
Integer
)
List1.AddRange(Task1.Result)
List1.AddRange(Task2.Result)
MsgBox(List1.Count)
End
Sub
Function
MyFunc()
As
ConcurrentBag(Of
Integer
)
' Dim ConCurrentBag1 As New ConcurrentBag(Of Integer)
For
index1
As
Integer
= 1
To
1000000
ConCurrentBag1.Add(index1)
Next
Return
ConCurrentBag1
End
Function
End
Class
如下代码每次单击运行都返回了400万,应该返回不确定的可变的数量。
上面的代码程序和本下面的代码程序源于发生同一个错误的。 这样说大家可能弄明白了.
|
Imports
System.Collections.Concurrent
Public
Class
Class1
Private
ConCurrentBag1
As
New
ConcurrentBag(Of
Integer
)
'在这里创建ConcurrentBag,运行结果发生错误。
Sub
MySub()
Dim
Task1
As
New
Task(Of ConcurrentBag(Of
Integer
))(
AddressOf
MyFunc)
Dim
Task2
As
New
Task(Of ConcurrentBag(Of
Integer
))(
AddressOf
MyFunc)
Task1.Start()
Task2.Start
Task1.Wait(
Task2.Wait(
Dim
List1
As
New
List(Of
Integer
)
List1.AddRange(Task1.Result)
List1.AddRange(Task2.Result)
MsgBox(List1.Count)
End
Sub
Function
MyFunc()
As
ConcurrentBag(Of
Integer
)
' Dim ConCurrentBag1 As New ConcurrentBag(Of Integer)
For
index1
As
Integer
= 1
To
1000000
ConCurrentBag1.Add(index1)
Next
Return
ConCurrentBag1
End
Function
End
Class
|
答案是MyFunc返回类型是引用地址类型。所以,先完成的第一线程返回任务之后,任务中的第二线程完成任务时,
先返回的第一线程原有的Result值进行更新,就是把第二线程完成之后的ConCurrentBag1值再次赋值给第一线程的Result。
接下来MySub过程是直到完成第二线程之后才能接受两个线程的返回数据。
所以,无法接收第一线程任务返回之后的数据,接收的只是第二线程完成后被再次更新后的数据.
所以,返回都不正确。
唯一解决方案是断开引用地址类型,操作方法是MyFunc的返回对象ConCurrentBag1进行转换连接,ConCurrentBag1.ToList,
然后,两个线程的任务返回类型改为
Dim Task1 As New Task(Of List(Of Integer))(AddressOf MyFunc)
Dim Task2 As New Task(Of List(Of Integer))(AddressOf MyFunc)
这样所有程序返回正常了.
另一种方式是MySub过程内的接受任务顺序优先方式安排。
第一程序的改变接收任务数据顺序如下;
Task1.RunSynchronously()
List1.AddRange(Task1.Result)
Task2.RunSynchronously()
List1.AddRange(Task2.Result)
MsgBox(List1.Count)
第二程序的改变接收顺序如下;
Task1.Start()
Task2.Start()
Task1.Wait()
List1.AddRange(Task1.Result)
Task2.Wait()
List1.AddRange(Task2.Result)
MsgBox(List1.Count)