C#中的异步多线程11 等待直到结束

最常用的异步是使用async/await特性和BackgroundWorker类,或者parallel并行库,但也可能会使用旧的模式来产生异步代码。

对于委托,当委托调用对象时,它调用了它的调用列表中包含的方法,这是同步完成的。

而如果委托对象在调用列表中只有一个方法(引用方法),它就可以异步执行这个方法。委托类有2个方法,叫做BeginInvoke和EndInvoke,他们就是用来异步执行的。

1、当调用委托的BeginInvoke方法时,它开始在一个独立线程上执行引用方法,并且立即返回到原始线程。原始线程可以继续,而引用方法会在线程池的线程中并行执行。

2、当程序希望获取已完成的异步方法的结果时,可以检查BeginInvoke返回的IActionResult的IsCompleted属性,或调用委托的EndInvoke方法来等待委托完成。

使用这一过程有3种模式:

1、等待-直到完成:发起异步方法后并进行了一些其他处理后,原始线程就中断并且等待异步方法完成之后再继续。

2、轮询:原始线程定期检查发起的线程是否完成,如果没有则可以继续做一些其他的事情。

3、回调:原始线程一直执行,无需等待或检查发起的线程是否完成。在发起的线程中的引用方法完成之后,发起的线程就会调用回调方法,由回调方法在调用EndInvoke之前处理异步方法的结果。

一、BeginInvoke和EndInvoke

在调用BeginInvoke时,参数列表中的实际参数如下:

1、引用方法需要的参数

2、两个额外的参数-callback参数和state参数

BeginInvoke从线程池中获取一个线程并且让引用方法在新的线程中开始运行。

BeginInvoke返回给调用线程一个实现IAsyncResult接口的对象的引用。这个接口引用包含了在线程池中运行的异步方法的当前状态,原始线程然后可以继续执行。

示例(等待直到结束):

原始线程发起一个异步方法的调用,做一些其他处理,然后停止并等待,直到开启的线程结束。

    
//声明委托类型 delegate long MyDel(int first,int second); class Program { static long Sum(int x,int y) { Console.WriteLine("Inside Sum"); Thread.Sleep(100); return x + y; } static void Main(string[] args) { MyDel del = new MyDel(Sum); Console.WriteLine("Before BeginInvoke"); IAsyncResult iar=del.BeginInvoke(3,5,null,null); Console.WriteLine("After BeginInvoke"); Console.WriteLine("Doing stuff"); long result = del.EndInvoke(iar); Console.WriteLine("After EndInvoke:{0}", result); Console.ReadLine(); } }

输出:

Before BeginInvoke
After BeginInvoke
Doing stuff
Inside Sum
After EndInvoke:8

说明:第一行声明了叫MyDel的委托类型。之后声明了一个匹配委托的Sum方法。

在Main函数中,声明了一个del示例,并且使用Sum方法初始化它的调用列表。然后调用了委托对象的BeginInvoke方法并且提供了两个委托参数3和5,以及两个BeginInvoke的参数callback和state,并设置为null,执行后BeginInvoke方法进行两个操作:

1、从线程池中获取一个线程并且在新的线程上开始运行Sum方法,将3和5作为实参

2、它手机新线程的状态信息并且把IAsyncResult接口的引用返回给调用线程来提供这些信息。调用线程把它保存在一个叫做iar的变量中。

EndInvoke方法来获取由异步方法调用返回的值,并且释放线程使用的资源。EndInvoke有如下特性:

1、它接受一个由BeginInvoke方法返回的IAsyncResult对象的引用,并找到它关联的线程

2、如果线程池的线程已经退出,EndInvoke做如下的事情:

      2-1、它清理退出线程的状态并且释放资源

      2-2、它找到引用方法返回的值并将它作为返回值

3、如果当EndInvoke被调用时线程池的线程仍然在运行,调用线程就会停止并等待,直到清理完毕并返回值。因为EndInvoke是为开启的线程进行清理,所以必须确保对每一个BeginInvoke都调用了EndInvoke。

4、如果异步方法触发了异常,在调用EndInvoke时会抛出异常。

//声明委托类型

猜你喜欢

转载自www.cnblogs.com/NicolasLiaoran/p/12960464.html