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

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

程序员文章站 2022-03-02 11:29:18
...

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并行与分布式编程(6)-线程与内核同步[9]
            
    
    博客分类: .net&silverlight  
 

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