我们继续扩展刚才的话题,再次使用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)
运行结果如下: