异步编程模式(一)
.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); //结束异步调用
//普通的代码:处于同步执行模式
//...............