吴佳鑫的个人专栏

当日事当日毕,没有任何借口

导航

异步编程模式(一)

.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);  //结束异步调用

//普通的代码:处于同步执行模式

//...............

posted on 2012-01-19 16:47  _eagle  阅读(912)  评论(1编辑  收藏  举报