吴佳鑫的个人专栏

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

导航

异步编程模式(五):实现 IAsyncResult 异步调用模式的组件

 

在.net 基类型库中,有一些现有的组件直接实现了 IAsyncResult 异步调用设计模式,这些组件通常同时提供某个方法的同步与异步调用形式。

 

以system.net 命名空间中的 WebRequest 为例,

如上图所示:有以下规律。

1.凡有一个 "BeginXXX"的,一定有一个"EndXXX"方法相对应。

2.每组"BeginXXX / EndXXX",一定有一个对应的 "XXX"方法。

3."EndXXX" 方法与对应的同步方法 "XXX"的返回值类型相同。

 

注意一下"BeginXXX"返回一个IAsyncResult 对象,而"EndXXX"方法的参数接收此对象。这种模式与前几节的基于委托的异步调用模式几乎一模一样,因此,前面所介绍

的各种编程技巧也大都可以继续使用。

 

 

示例程序:(使用WebRequest启动多个异步下载Web网页的任务)

程序采用异步回调的方式通知用户文件下载完毕,回调方法的名字为DownloadFinished.

为了向回调方法传送任务信息,程序设计了一个 DownLoadTask 类封装相关的信息:

    public class DownLoadTask
{
//用于下载文件的WebRequest对象
public WebRequest WebRequestObject { get; set; }
//用于保存下载文件的文件名
public string SaveToFileName { get; set; }
}

 

以下是主函数

        static void Main(string[] args)
{
string UserInputUrl = "";
string FileName = "";
Console.WriteLine("输入URL启动一个异步下载Web文件任务,输入quit退出。");
do
{

Console.Write("\n输入Web文件的URL:");
UserInputUrl = Console.ReadLine();
if (string.IsNullOrEmpty(UserInputUrl))
{
Console.WriteLine("不能输入一个空的URL字串");
continue;
}
if (UserInputUrl.ToLower() == "quit")
break;
Console.Write("输入要保存的文件名:");
FileName = Console.ReadLine();
if (string.IsNullOrEmpty(FileName))
{
Console.WriteLine("不能输入一个空的URL字串");
continue;
}
if (FileName.ToLower() == "quit")
break;

if (UserInputUrl.ToLower() == "quit")
break;
try
{
//以下代码启动异步下载:
Uri webFileUri = new Uri(UserInputUrl);
WebRequest webRequest = WebRequest.Create(webFileUri);

//封装任务信息
DownLoadTask task = new DownLoadTask { SaveToFileName = FileName, WebRequestObject = webRequest };
Console.WriteLine("已在后台启动下载{0}", FileName);
//启动异步下载,指明异步回调DownloadFinished,并向其传送任务信息参数
webRequest.BeginGetResponse(DownloadFinished, task);

}
catch (Exception ex)
{

Console.WriteLine(ex.Message);
}



} while (true);

Console.WriteLine("\n敲任意键结束本示例程序...");

Console.ReadKey();
}

 

以下是回调方法:

        /// <summary>
/// 异步回调函数
/// </summary>
/// <param name="ar"></param>
static void DownloadFinished(IAsyncResult ar)
{
try
{
//获取相关任务信息
DownLoadTask task = ar.AsyncState as DownLoadTask;
//结束异步调用
WebResponse response = task.WebRequestObject.EndGetResponse(ar);
string FileContent="";
using(StreamReader reader=new StreamReader(response.GetResponseStream(),Encoding.GetEncoding("gb2312")))
{
FileContent = reader.ReadToEnd();
}

using (StreamWriter writer = new StreamWriter(new FileStream(task.SaveToFileName, FileMode.Create), Encoding.GetEncoding("gb2312")))
{
writer.Write(FileContent);
}

MessageBox.Show(string.Format("“{0}”下载完成!", task.SaveToFileName));
}

catch (Exception ex)
{
MessageBox.Show(ex.Message);
}

}




posted on 2012-02-01 13:52  _eagle  阅读(594)  评论(0编辑  收藏  举报