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

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

3)使用委托的异步调用实现多线程的参数转入和传出

A)基础知识

a)Delegate 类是委托类型的基类。然而,只有系统和编译器可以显式地从 Delegate 类或 MulticastDelegate 类派生。此外,还不允许从委托类型派生新类型。Delegate 类不是委托类型,该类用于派生委托类型, 应当使用语delegate 关键字声明。

b)委托类型的声明建立了一个协定,该协定指定一个或多个方法的签名。

c)委托的调用列表就是已排序的委托集,其中列表的每个元素恰好调用该委托表示的一个方法。调用列表可以包含重复的方法。在调用期间,按方法出现在调用列表中的顺序来调用它们。

d)委托试图调用其调用列表中的每个方法,而重复方法在调用列表中出现一次就调用一次。委托是不可变的;一旦创建,委托的调用列表便无法更改。

e)委托被称作多路广播委托或可组合委托,因为委托可以调用一种或多种方法,并且可以用在组合操作中。

f)合并操作(如 Combine 和 Remove)并不改变现有委托。相反,这样的操作返回一个新委托,其中包含操作结果、未更改的委托或 空引用(在 Visual Basic 中为 Nothing)。当合并操作的结果是没有引用任何方法的委托时,该操作返回 空引用(在 Visual Basic 中为 Nothing)。当所请求的操作无效时,合并操作返回未更改的委托。

g)如果所调用的方法引发异常,则方法停止执行,并将异常向回传递给委托的调用方,且不再调用调用列表中其余的方法。捕捉调用方的异常并不改变此行为。

h)当委托所调用的方法的签名包含返回值时,委托返回调用列表中最后一个元素的返回值。当签名包含由引用传递的参数时,该参数的最终值就是调用列表中每个方法的结果,这些方法依序执行并更新参数的值。

i)编译器为委托提供两种其他方法:BeginInvoke 和 EndInvoke。

a.  BeginInvoke 方法可启动异步调用。它与您需要异步执行的方法具有相同的参数,另外它还有两个可选参数。第一个参数是一个 AsyncCallback 委托,该委托引用在异步调用完成时要调用的方法。第二个参数是一个用户定义的对象,该对象可向回调方法传递信息。BeginInvoke 立即返回,不等待异步调用完成。BeginInvoke 会返回 IAsyncResult,这个结果可用于监视异步调用进度。

b. EndInvoke 方法检索异步调用的结果。调用 BeginInvoke 后可随时调用 EndInvoke 方法;如果异步调用尚未完成,EndInvoke 将一直阻止调用线程,直到异步调用完成后才允许调用线程执行。EndInvoke 的参数包括您需要异步执行的方法的 out 和 ref 参数(在 Visual Basic 中为 <Out> ByRef 和 ByRef)以及由 BeginInvoke 返回的 IAsyncResult

 c. 异步执行方法最简单的方式是通过调用委托的 BeginInvoke 方法来开始执行方法,在主线程上执行一些工作,然后调用委托的 EndInvoke 方法。EndInvoke 可能会阻止调用线程,因为它直到异步调用完成之后才返回。这种技术非常适合文件或网络操作,但是由于 EndInvoke 会阻止它,所以不要从服务于用户界面的线程中调用它。

 

B)其它知识

OutAttribute 类

指示应将数据从被调用方封送回调用方。

EndInvoke 的参数包括需要异步执行的方法 <Out> ByRef 和 ByRef 以及由 BeginInvoke 返回的 IAsyncResult。

 

 

IAsyncResult 接口

 

IAsyncResult 接口

由包含可异步操作的方法的类实现。 它是启动异步操作的方法(如 FileStream.BeginRead)的返回类型,也是结束异步操作的方法(如 FileStream.EndRead)的第三个参数的类型。 当异步操作完成时,IAsyncResult 对象也将传递给由 AsyncCallback 委托调用的方法。

 

 

支持 IAsyncResult 接口的对象存储异步操作的状态信息,并提供同步对象以允许线程在操作完成时终止。


 AsyncResult 类是在使用委托异步调用方法时 BeginInvoke 方法返回的 IAsyncResult 的实现。

 

 

C)下面我们将继续刚才的连续累加的例子,说明如何使用委托的异步调用来实现多线程编程,注意委托的异步调用仍然是在进程的.NET线程池中分配的线程来执行的,虽然没有显示地使用.NET线程池。

D)我们先以一个工作线程、一个主线程为例进行说明:

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(1000, threadid, Nothing, Nothing)
        Thread.Sleep(0)
        Console.WriteLine("{0},开始执行线程,主线程{1}号正在等待...", Now.ToLongTimeString, Thread.CurrentThread.ManagedThreadId)

        '等待异步调用完成,主线程才返回
        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(0)
            Next
            Console.WriteLine(threadid & "号线程  " & Now.ToLongTimeString & "线程运行完毕!")
        Catch
            Console.WriteLine(threadid & "号线程  " & Now.ToLongTimeString & "线程异常终止!")
            '终止线程
            Thread.CurrentThread.Abort()
        End Try
        Return jg
    End Function
End Module

 

 

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