VB.NET并行与分布式编程(6)-线程与内核同步[11]
Imports System Imports System.Threading Imports System.Runtime.InteropServices Imports System.Diagnostics Imports System.Diagnostics.ThreadState Module Module1 '定义异步方法 Delegate Function myAdds(ByVal num As Integer, <Out()> ByRef threadid As Integer) As Long <MTAThread()> _ Sub Main() '定义IAsyncResult Dim myasyncresult As IAsyncResult '定义需要异步执行的方法 Dim myadd As myAdds = New myAdds(AddressOf mythreadrun) '定义计算结果存放处 Dim resultvalue As Long '异步线程调用号 Dim threadid As Integer '异步调用 myasyncresult = myadd.BeginInvoke(5000, threadid, Nothing, Nothing) Thread.Sleep(0) Console.Write("{0},开始执行线程,主线程{1}号正在等待", Now.ToLongTimeString, Thread.CurrentThread.ManagedThreadId) '等待并执行其它代码 While Not myasyncresult.IsCompleted Console.Write(".") Thread.Sleep(10) End While '异步调用完成,返回结果 resultvalue = myadd.EndInvoke(threadid, myasyncresult) '线程执行完毕 Console.WriteLine("{0}号线程计算结果为:{1}", threadid, resultvalue) End Sub Public Function mythreadrun(ByVal num As Integer, <Out()> ByRef threadid As Integer) As Long Dim mynum As Integer Dim jg As Long = 0 threadid = Thread.CurrentThread.ManagedThreadId Try For mynum = 1 To num jg += mynum Thread.Sleep(1) Next Console.WriteLine(threadid & "号线程 " & Now.ToLongTimeString & "线程运行完毕!") Catch Console.WriteLine(threadid & "号线程 " & Now.ToLongTimeString & "线程异常终止!") '终止线程 Thread.CurrentThread.Abort() End Try Return jg End Function End Module
上面的代码中, 我们使用IAsyncResult的IsCompleted属性完成上节代码类似的功能,轮询工作线程,如果工作线程没有完成,则IsCompleted为False,则主线程继续自己的工作,输出一个点,同时再休眠10秒
While Not myasyncresult.IsCompleted
Console.Write(".")
Thread.Sleep(10)
End While
前面几个异步调用的例子,我们都在主线程对计算结果进行输出,我们下面把输出计算结果的工作移到回调方法中,启动异步调用,我们可以传递一个回调函数做为参数给BeginInvoke,由回调函数对工作线程,即被调用的线程的结果进行处理,主线程不再处理。
有几个小知识点
a)IAsyncResult.AsyncState 属性
获取用户定义的对象,它限定或包含关于异步操作的信息。
此属性返回一个对象,该对象是启动异步操作的方法的最后一个参数。
使用AsyncState 属性来向回调方法传递信息。
被调用者实现此属性以允许异步操作的调用方获取在操作开始指定的应用程序定义的对象。
调用者可以使用此对象将异步操作的状态信息传递给回调函数。
Public Sub myfinished(ByVal ar As IAsyncResult)
'回调函数完成将计算结果显示的功能,不再在主线程中显示计算结果
Dim threadid As Integer
Dim caller As myAdds = CType(ar.AsyncState, myAdds)
Dim returnvalue As Long = caller.EndInvoke(threadid, ar)
Console.WriteLine("工作线程{0}号执行完毕,计算结果为{1}", threadid, returnvalue)
End Sub
b)异步调用的最后一个参数就是传递给回调函数的,我们在这里把需要异步执行的方法myadd传入,方法对象会存入
IAsyncResult.AsyncState 属性中
myasyncresult = myadd.BeginInvoke(5000, threadid, AddressOf myfinished, myadd)
完整代码如下:
Imports System Imports System.Threading Imports System.Runtime.InteropServices Imports System.Diagnostics Imports System.Diagnostics.ThreadState Module Module1 '定义异步方法 Delegate Function myAdds(ByVal num As Integer, <Out()> ByRef threadid As Integer) As Long <MTAThread()> _ Sub Main() '定义IAsyncResult Dim myasyncresult As IAsyncResult '定义需要异步执行的方法 Dim myadd As myAdds = New myAdds(AddressOf mythreadrun) '定义计算结果存放处 Dim resultvalue As Long '异步线程调用号 Dim threadid As Integer '异步调用 myasyncresult = myadd.BeginInvoke(5000, threadid, AddressOf myfinished, myadd) Console.WriteLine("{0},开始执行线程,主线程{1}号正在等待", Now.ToLongTimeString, Thread.CurrentThread.ManagedThreadId) Thread.Sleep(0) Console.WriteLine("工作线程正在运行,按任意健结束主线程.....") Console.ReadLine() End Sub Public Function mythreadrun(ByVal num As Integer, <Out()> ByRef threadid As Integer) As Long Dim mynum As Integer Dim jg As Long = 0 threadid = Thread.CurrentThread.ManagedThreadId Try For mynum = 1 To num jg += mynum Thread.Sleep(1) Next Console.WriteLine(threadid & "号线程 " & Now.ToLongTimeString & "线程运行完毕!") Catch Console.WriteLine(threadid & "号线程 " & Now.ToLongTimeString & "线程异常终止!") '终止线程 Thread.CurrentThread.Abort() End Try Return jg End Function Public Sub myfinished(ByVal ar As IAsyncResult) '回调函数完成将计算结果显示的功能,不再在主线程中显示计算结果 Dim threadid As Integer Dim caller As myAdds = CType(ar.AsyncState, myAdds) Dim returnvalue As Long = caller.EndInvoke(threadid, ar) Console.WriteLine("工作线程{0}号执行完毕,计算结果为{1}", threadid, returnvalue) End Sub End Module