.NET(C#) 使用BeginInvoke()和EndInvoke()实现异步
.NET Framework允许异步调用任何方法。定义与需要调用的方法具有相同签名的委托;公共语言运行库将自动为该委托定义具有适当签名的 BeginInvoke 和 EndInvoke 方法。本文主要介绍.NET(C#)中,通过BeginInvoke()和EndInvoke()实现异步。
1、异步编程
调用BeginInvoke
可以执行任务,然后调用EndInvoke阻塞直到调用完成。使用IAsyncResult.AsyncWaitHandle
属性获取WaitHandle
,使用其WaitOne
方法阻止执行,直到发出WaitHandle
信号,然后调用EndInvoke
轮询返回的IAsyncResultBeginInvoke
以确定异步调用何时完成,然后调用EndInvoke
。
将回调方法的委托传递给BeginInvoke
。当异步调用完成时,该方法在ThreadPool
线程上执行。回调方法调用EndInvoke
。BeginInvoke
立即返回,不等待异步调用完成。BeginInvoke
返回 IasyncResult
,可用于监视调用进度。EndInvoke
方法用于检索异步调用结果。调用 BeginInvoke
后可随时调用 EndInvoke
方法;如果异步调用未完成,EndInvoke
将一直阻塞到异步调用完成。
2、同步方法和异步方法区别
同步方法调用在程序继续执行之前,需要等待同步方法执行完毕返回结果,异步方法则在被调用之后,立即返回以便程序在被调用方法完成其任务的同时执行其它操作。
3、异步操作的优缺点
异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量,即使无法完全不用,最起码可以减少共享变量的数量,减少了死锁的可能。当然异步操作也并非完美。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些初入,而且难以调试。
4、BeginInvoke()和EndInvoke()的使用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApplication { class Program { static void Main(string[] args) { Func<DateTime> func = () => { Thread.Sleep(1000); return DateTime.Now; }; Console.WriteLine($"func.Invoke()={func.Invoke()}"); //EndInvoke(r)用来获取执行后的返回值,BeginInvoke()的第一个参数是func执行完成后回调用函数 IAsyncResult asyncResult = func.BeginInvoke(r => { //Console.WriteLine(func.EndInvoke(r)); Console.WriteLine(r.AsyncState); }, "cjavapy"); //asyncResult.AsyncWaitHandle.WaitOne();一直等到完成后,才会执行下一行代码 //asyncResult.AsyncWaitHandle.WaitOne(5000);指定等待超时的时间为5s Console.WriteLine(func.EndInvoke(asyncResult)); //Thread.Sleep(6000); } } }
注意:EndInvoke()
获取返回值只能调用一次,不能重复调用。