我们继续扩展刚才的话题,再次使用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
上段代码定义了一个属性,可以理解为“自动实现的属性”,可以快速指定类的属性,而无需编写代码对该属性执行 Get 和 Set 操作。 在为自动实现的属性编写代码时,除了创建关联的 Get 和 Set 过程之外,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)
运行结果如下: