欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

VB.NET并行与分布式编程(6)-线程与内核同步[7]

程序员文章站 2022-03-02 11:28:06
...

我们继续扩展刚才的话题,再次使用WaitAny完成一个简单的任务,求100以内阶乘之和

 

完成这个任务我们先来解决几个问题

1、如何将线程计算结果传出来,参数可以传入,而且只能传入一个,如何传入多个参数,并输出多个参数?

1)最经典的方法是定义一个类,这个类存放了传入的参数和传出的参数

Imports System
Imports System.Threading
Imports System.Diagnostics
Imports System.Diagnostics.ThreadState


Module Module1

    <MTAThread()> _
    Sub Main()





        '完成任务的线程号
        Dim finishedid As Integer
        '自己创建线程对象数组(不使用.NET的线程池),共5个线程
        Dim mythread(4) As Thread
        '分别给每个线程创建一个线程信号类对象,保存AutoResetEvent对象和计算结果
        Dim calculateifno(4) As CalculateIfno
        Dim threadevent(4) As AutoResetEvent

        For i = 0 To mythread.GetUpperBound(0)
            mythread(i) = New Thread(AddressOf mythreadrun)
            mythread(i).Name = "thread_" & i
        Next
        Console.WriteLine(Now.ToLongTimeString & "线程对象创建完毕,开始执行线程")
        mythread(4).Priority = ThreadPriority.AboveNormal
        '设置线程执行前相关参数,并执行线程,将参数对象传入线程
        For i = 0 To mythread.GetUpperBound(0)
            '设置参数对象
            calculateifno(i) = New CalculateIfno
            calculateifno(i).threadevent = New AutoResetEvent(False)
            calculateifno(i).result = 0
            threadevent(i) = calculateifno(i).threadevent
            '将参数对象传入线程并执行
            mythread(i).Start(calculateifno(i))
        Next
        '等待其中一个线程完成累加,然后将其它未完成任务的线程终止 
        finishedid = WaitHandle.WaitAny(threadevent)
        For i = 0 To mythread.GetUpperBound(0)
            If i <> finishedid Then
                mythread(i).Abort()
            End If
        Next
        '线程执行完毕
        Console.WriteLine(Now.ToLongTimeString & "    " & finishedid & "号线程完成任务,计算完毕!" & Environment.NewLine & "计算结果为:" & calculateifno(finishedid).result)
    End Sub
    Public Class CalculateIfno
        Private _threadevent As AutoResetEvent
        Private _result As Long
        Public Property threadevent As AutoResetEvent
            Get
                Return _threadevent
            End Get
            Set(ByVal value As AutoResetEvent)
                _threadevent = value
            End Set

        End Property
        Public Property result As Long
            Get
                Return _result
            End Get
            Set(ByVal value As Long)
                _result = value
            End Set
        End Property
    End Class

    Public Sub mythreadrun(ByVal calculateifno As Object) As Integer
        Dim mynum As Integer
        Dim jg As Long = 0
        Try
            For mynum = 1 To 1000
                jg += mynum
                Thread.Sleep(5)
            Next
            Console.WriteLine(Thread.CurrentThread.Name & "  " & Now.ToLongTimeString & "线程运行完毕!")
        Catch
            Console.WriteLine(Thread.CurrentThread.Name & "  " & Now.ToLongTimeString & "线程异常终止!")
            '终止线程
            Thread.CurrentThread.Abort()
        Finally
            CType(calculateifno, CalculateIfno).threadevent.Set()
            CType(calculateifno, CalculateIfno).result = jg
        End Try
    End Sub
End Module

 

 以上代码有几个重点要分析一下

1)VB.NET类的属性定义

  Public Class CalculateIfno
        Private _threadevent As AutoResetEvent
        Private _result As Long
        Public Property threadevent As AutoResetEvent
            Get
                Return _threadevent
            End Get
            Set(ByVal value As AutoResetEvent)
                _threadevent = value
            End Set

        End Property
        Public Property result As Long
            Get
                Return _result
            End Get
            Set(ByVal value As Long)
                _result = value
            End Set
        End Property
    End Class 

 

上述类定义中

  Public Property threadevent As AutoResetEvent
            Get
                Return _threadevent
            End Get
            Set(ByVal value As AutoResetEvent)
                _threadevent = value
            End Set

        End Property
上段代码定义了一个属性,可以理解为“自动实现的属性”,可以快速指定类的属性,而无需编写代码对该属性执行 GetSet 操作。 在为自动实现的属性编写代码时,除了创建关联的 GetSet 过程之外,Visual Basic 编译器还会自动创建一个私有字段来存储该属性变量。

 2)线程函数中对传进来的对象的相关属性的赋值和操作

        Finally
            CType(calculateifno, CalculateIfno).threadevent.Set()
            CType(calculateifno, CalculateIfno).result = jg
        End Try

3)读取线程传出来的结果

        Console.WriteLine(Now.ToLongTimeString & "    " & finishedid & "号线程完成任务,计算完毕!" & Environment.NewLine & "计算结果为:" & calculateifno(finishedid).result)

 

运行结果如下:


VB.NET并行与分布式编程(6)-线程与内核同步[7]
            
    
    博客分类: .net&silverlight  
 

  • VB.NET并行与分布式编程(6)-线程与内核同步[7]
            
    
    博客分类: .net&silverlight  
  • 大小: 40.1 KB