.net 的异步编程技术主要分为两个块:
1、使用IAsyncResult 的异步编程模式。
2、基于事件的异步编程模式。
C#编译器会为每个委托生成支持异步执行的 BeginInvoke / EndInvoke 方法,从而将委托和异步编程紧密联系起来了。
当同步执行程序时,如果执行到需要执行较长时间的代码时,用户必须等待,也会认为程序已经卡死或死机了。
同步程序的示例代码如下:
namespace CalculateFolderSizeNoAsync { class Program { //计算指定文件夹的总容量 private static long CalculateFolderSize(string FolderName) { if (Directory.Exists(FolderName) == false) { throw new DirectoryNotFoundException("文件夹不存在"); } DirectoryInfo RootDir = new DirectoryInfo(FolderName); //获取所有的子文件夹 DirectoryInfo[] ChildDirs = RootDir.GetDirectories(); //获取当前文件夹中的所有文件 FileInfo[] files = RootDir.GetFiles(); long totalSize = 0; //累加每个文件的大小 foreach (FileInfo file in files) { totalSize += file.Length; } //对每个文件夹执行同样的计算过程:累加其下每个文件的大小 //这是通过递归调用实现的 foreach (DirectoryInfo dir in ChildDirs) { totalSize += CalculateFolderSize(dir.FullName); } //返回文件夹的总容量 return totalSize; } static void Main(string[] args) { long size; string FolderName; Console.WriteLine("请输入文件夹名称(例如:C:\\Windows):"); FolderName = Console.ReadLine(); size = CalculateFolderSize(FolderName); Console.WriteLine("\n文件夹{0}的容量为:{1}字节\n", FolderName , size); Console.ReadKey(); } } }
程序中调用了CalculateFolderSize方法,如果此方法不返回,下面的代码是不可能执行的。
如果这个方法执行时间很长,则用户在方法返回前是看不到任何信息的,他有可能会以为计算机死机了。
上述程序就是典型的程序同步执行模式。
能不能在调用方法后,不用等待方法执行完成就马上执行下一条语句?
要实现 这个功能,就必须采用“异步编程模式”
如下代码示例:
namespace AsyncCalculateFolderSize1 { class Program { //计算指定文件夹的总容量 private static long CalculateFolderSize(string FolderName) { if (Directory.Exists(FolderName) == false) { throw new DirectoryNotFoundException("文件夹不存在"); } DirectoryInfo RootDir = new DirectoryInfo(FolderName); //获取所有的子文件夹 DirectoryInfo[] ChildDirs = RootDir.GetDirectories(); //获取当前文件夹中的所有文件 FileInfo[] files = RootDir.GetFiles(); long totalSize = 0; //累加每个文件的大小 foreach (FileInfo file in files) { totalSize += file.Length; } //对每个文件夹执行同样的计算过程:累加其下每个文件的大小 //这是通过递归调用实现的 foreach (DirectoryInfo dir in ChildDirs) { totalSize += CalculateFolderSize(dir.FullName); } //返回文件夹的总容量 return totalSize; } //定义一个委托 public delegate long CalculateFolderSizeDelegate(string FolderName); static void Main(string[] args) { //定义一个委托变量引用静态方法CalculateFolderSize CalculateFolderSizeDelegate d = CalculateFolderSize; Console.WriteLine("请输入文件夹名称(例如:C:\\Windows):"); string FolderName = Console.ReadLine(); //通过委托异步调用静态方法CalculateFolderSize IAsyncResult ret=d.BeginInvoke(FolderName,null,null); Console.WriteLine("正在计算中,请耐心等待……"); //阻塞,等到调用完成,取出结果 long size = d.EndInvoke(ret); Console.WriteLine("\n计算完成。文件夹{0}的容量为:{1}字节\n", FolderName, size); Console.ReadKey(); } } }
本示例的异步编程方式是通过委托来实现的。
通过创建一个引用静态方法CalculateFolderSize 的委托变量d,第4句通过调用委托对象d 的 BeginInvoke 方法间接地调用静态方法CalculateFolderSize 不在主线程中执行
,而在另一个辅助纯种中与主线程代码并行 执行,由于存在两个并行的线程,所以启动执行静态方法CalculateFilderSize 之后,并不会等待其完成,而是马上执行下一句,输
出一句提示信息。
从这个典型的异步调用程序中,可以知道异步调用 的一种通用的编程模式是:
//..............
//普通的代码:处于同步执行模式
IAsyncResult ret = 委托变量.BeginInvoke(......); //启动异步调用
//可以在这一部分做其他一些事,程序处于异步执行模式
用于保存方法结果的变量 = 委托变量.EndInvoke(ret); //结束异步调用
//普通的代码:处于同步执行模式
//...............