应用多线程时的注意事项


如下程序同步运行后返回不正确 ,应该返回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万,应该返回不确定的可变的数量。

上面的代码程序和本下面的代码程序源于发生同一个错误的。 这样说大家可能弄明白了.

Visual Basic code







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)




















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值